C# 测量多种方法的执行时间
我在WPF的项目中工作,该项目使用实体框架和SQL Server。那里的优化是废话。一切都太慢了。我想诊断代码的哪些部分会影响性能——我认为只有少数(我指的是很多,但不是全部)地方设计糟糕,会影响性能 现在,对于我们有类的每个表,例如C# 测量多种方法的执行时间,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我在WPF的项目中工作,该项目使用实体框架和SQL Server。那里的优化是废话。一切都太慢了。我想诊断代码的哪些部分会影响性能——我认为只有少数(我指的是很多,但不是全部)地方设计糟糕,会影响性能 现在,对于我们有类的每个表,例如UserRepository。这并不完全是存储库模式。这些类有如下方法:GetAll(…)、GetById(…)、getnewst(…)、GetAllWithHigherSalaryThan(int-salary、int-companyId),等等,许多方法访问数据
UserRepository
。这并不完全是存储库模式。这些类有如下方法:GetAll(…)、GetById(…)、getnewst(…)、GetAllWithHigherSalaryThan(int-salary、int-companyId)
,等等,许多方法访问数据库。数据库仅在存储库类中使用
我不想在这里谈论重构。我只想测量每个方法执行多长时间,以及在运行时执行了多少次。通过这些信息,我将能够找到bug
我想测量大约100个方法,这些方法在很多类中都有“从db中选择”。
SQLServerProfiler并没有做到这一点,因为这些方法执行了无数次,如果可能的话,使用我们的数据库方法分析来自Profiler的日志是一场噩梦
抽样方法:
public IEnumerable<Foo> GetFoo(int y, int z)
{
return Context.Where(p =>
p.X == null &&
p.Y == y &&
p.Time >= z).OrderBy(x => x.Time).AsEnumerable();
}
public IEnumerable GetFoo(inty,intz)
{
返回上下文。其中(p=>
p、 X==null&&
p、 Y==Y&&
p、 Time>=z).OrderBy(x=>x.Time).AsEnumerable();
}
现在我正在考虑在每个方法中添加秒表,测量执行时间,计算执行次数,并将其传递给某个单例或其他对象,然后显示它。当然,当我完成诊断后,我会关闭它,但这种方法非常简单,我需要编辑每个方法,我不知道如何在之后关闭它-我的意思是我知道我可以使用类似#define DEBUG
的东西,但无论如何它都是蹩脚的
我试图通过思考找出一些问题,但没有效果。。。也许有一种方法可以在C#中查看方法的执行时间
你推荐什么 语言本身没有内置的分析器。如果您不介意指定所使用的内容,您的IDE/调试器可能有一些内置的探查器 如果您正在运行MSSQL(如图所示),您可能无法以适合您的方式进行评测。这里有两个问题对我起了神奇的作用:
SELECT TOP 10 SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(qt.TEXT)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2)+1),
qs.execution_count,
qs.total_logical_reads, qs.last_logical_reads,
qs.total_logical_writes, qs.last_logical_writes,
qs.total_worker_time,
qs.last_worker_time,
qs.total_elapsed_time/1000000 total_elapsed_time_in_S,
qs.last_elapsed_time/1000000 last_elapsed_time_in_S,
qs.last_execution_time,
qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_logical_reads DESC -- logical reads
-- ORDER BY qs.total_logical_writes DESC -- logical writes
-- ORDER BY qs.total_worker_time DESC -- CPU time
这里的神奇之处在于,您可以找出哪些命令总体上占用的时间最多,而不管它是一个运行速度非常慢的命令10次,还是一个运行1000000次但非常快的命令
你也可能会得到一些更高的东西。我以前可以通过在每个web请求的开头和结尾附加一个探查器来调试项目,但这同样无法找到导致问题的特定命令。我的第一个建议是一个合适的探查器,我最喜欢的是Jetbrains的dotTrace,但还有其他建议 如果不知何故,这不是一个选项,而您坚持自己去做: 我推荐Postsharp或其他AOP软件包。它可以做的是轻松地向许多方法添加方面 使用Postsharp,您可以编写一个方面:
[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
// start measuring time here
}
public override void OnExit( MethodExecutionArgs args )
{
// stop measuring here
}
}
然后将该方面应用于一组方法(MyNamespace中的所有公共方法):
这就是同时为许多方法提供工具所需的全部代码
我最近做了这件事,我把所有的测量数据转储到csv文本文件中,然后将其转储到SQL Server中,在那里我可以很容易地进行选择和分组,例如找出一个方法所消耗的总时间。我没有使用分析器,因为我是在生产环境中进行测量的——仪器对性能的影响不大(如果程序运行缓慢的话)
以下是关于这方面的更多信息:
即使是免费版本的PostSharp Express也足以做到这一点。您是否尝试过使用VS profiler,它在VS2012及更高版本中非常好?我必须说,您看过非常漂亮的软件吗!我喜欢这种干净的方法。我还使用了一种包装器方法来做同样的事情,但它是日志框架的一部分,然后将执行时间和其他数据记录到数据库中。在这里,我认为你的方法非常适合。
[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args )
{
// start measuring time here
}
public override void OnExit( MethodExecutionArgs args )
{
// stop measuring here
}
}
#if DEBUG
[assembly: Trace( AttributeTargetTypes = "MyNamespace.*",
AttributeTargetTypeAttributes = MulticastAttributes.Public,
AttributeTargetMemberAttributes = MulticastAttributes.Public )]
#endif