DbContext / Ninject Dependency GetService Slow SingleOrDefault在Load Test下

时间:2015-02-09 16:52:58

标签: c# entity-framework ninject

我为这篇长篇文章提前道歉,因为我一直在收集诊断信息,但似乎无法解决问题。

EF6 / Web API 2

  

首先,我注意到一个运行缓慢的终端,并且在负载测试下情况会变得更糟。

代码:

//configuration
kernel.Bind<T>()
.To<T>()
.InTransientScope()

//Caller elsewhere in code base
public http.IDependencyScope BeginScope()
{
   return new NinjectScope(_kernel.BeginBlock());
}


public class NinjectScope : IDependencyScope
{
  public object GetService(Type serviceType)
  {
     Debug.WriteLine("COREIOC_Enter GetService Timein: {0}", DateTime.Now.ToLongTimeString());
     Stopwatch coreIOC = new Stopwatch();
     coreIOC.Start();

    IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
    Debug.WriteLine(string.Format("COREIOC_Complete CreateRequest Elapsed: {0}", coreIOC.Elapsed));

    var abc = resolutionRoot.Resolve(request);
    Debug.WriteLine(string.Format("COREIOC_Resolve Elapsed: {0}", coreIOC.Elapsed));

    var xyz = abc.SingleOrDefault();
    Debug.WriteLine(string.Format("COREIOC_SingleDef Resolve Elapsed: {0}", coreIOC.Elapsed));

    coreIOC.Stop();
    Debug.WriteLine(string.Format("COREIOC_Exit  Elapsed: {0}", coreIOC.Elapsed));

    return xyz;
  }
}

调试输出:(注意SingleDef为4秒)

COREIOC_Enter GetService Timein: 7:15:56 AM:
COREIOC_Complete CreateRequest Elapsed: 00:00:00.0008914
COREIOC_Resolve Elapsed: 00:00:00.0032197    
COREIOC_SingleDef Resolve Elapsed: 00:00:04.4787988
COREIOC_Exit  Elapsed: 00:00:04.4803695
  

有趣的是,随后的调用显示了这个&#34;旋转&#34;时间不见了

COREIOC_Enter GetService Timein: 7:27:08 AM:
COREIOC_Complete CreateRequest Elapsed: 00:00:00.0000266
COREIOC_Resolve Elapsed: 00:00:00.0018957
COREIOC_SingleDef Resolve Elapsed: 00:00:00.0307401
COREIOC_Exit  Elapsed: 00:00:00.0354408

所以这将是一个开放和关闭的情况 EXCEPT 在负载测试下,端点显示每次呼叫的4秒延迟。 (例如,同时进行250次测试会显示每次测试时间超过4秒。)

手写负载测试代码:

public override IEnumerator<WebTestRequest> GetRequestEnumerator()
{
   WebTestRequest request6 = new WebTestRequest("http://localhost:57874/api/acts/10553697");
   request6.Timeout = 120;
   request6.Method = "GET";
   request6.Headers.Add(new WebTestRequestHeader("Authorization", "Bearer h0aHdT6..."));
   request6.Headers.Add(new WebTestRequestHeader("Accept","application/..."));
   request6.Headers.Add(new WebTestRequestHeader("ContentType", "application/json"));
   request6.ValidateResponse += new EventHandler<ValidationEventArgs>(request6_ValidateResponse);
   yield return request6;
   request6 = null;
}

所以

  1. 是我的负载测试错误OR,
  2. 是我的EF 6设置错误OR,
  3. 是我的对象重用不正确OR,
  4. 我实际使用SingleOrDefault有问题吗?
  5. 我经历过ninject实例化的对象的构造函数,并且没有看到任何内容导致延迟。

    我确实遇到了这个SO post,作为PluralSight的粉丝,我能够立即访问该课程。然而,这是一个七小时的课程,最后我不确定它是导致延迟的EF。

1 个答案:

答案 0 :(得分:0)

对于关注的任何人抱歉。我想出来了,但忘了在这里更新。

所以你可以说问题出在Ninject上......但是你也可以做出一个强有力的案例就是我们的设计就是问题。

在一天结束时,我会说这是我们的设计问题。一点点的Ninject灵活性可能会让设计不再成为一个问题,但如果一个糟糕的设计永远不会出现问题,那么设计仍然很糟糕吗?

无论如何,我们的终端在他们将要执行的操作中是灵活的。这很好,除了Ninject,即使不需要,也会构建一切。

例如,一个终点可能有13个注入的对象,但对于给定的操作,只需要3.(其他10个将被其他消费者使用)。

无论是否需要3个Ninject都会实例化所有13个并且在10分钟750个恒定负载下...这就是JITting的大量进展。

因此,针对更具体的目的突破了几个终点,并且jit时间急剧下降。

从上面的例子中可以看出:

一个端点上的13个注入对象变为:

  1. 3个注入的对象
  2. 5个注入的物品
  3. 4个注入的物体
  4. 3个注入的对象
  5. 因此,端点1-4不会增加到13,因为现在有一些冗余。在一些端点注入相同的对象,但在一天结束时,所有内容都按照我们的预期在负载下执行。