[英]Getting the caller method name - Reflection and CallerInfo attribute
Just bench-marked the performance of using StackTrace
and CallerInfo Attributes
. 刚刚基准化了使用
StackTrace
和CallerInfo Attributes
的性能。
Shockingly I found that using StackTrace
is much faster though every where I read that To get the caller method name, the preferred approach is CallerInfo attributes
. 令人震惊的是,我发现使用
StackTrace
的速度要快得多,尽管在每个地方我都读到它。 To get the caller method name, the preferred approach is CallerInfo attributes
。
public class Program
{
public static void Main(string[] args)
{
Method1();
}
static void Method1([CallerMemberName]string memberName = "")
{
double stackTraceTimings = 0;
var sw = new Stopwatch();
foreach(var item in Enumerable.Range(1,1000).ToList())
{
sw.Start();
var callerName = new StackFrame(1).GetMethod().Name;
sw.Stop();
stackTraceTimings += sw.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations ={0}",stackTraceTimings/1000);
stackTraceTimings = 0;
foreach(var item in Enumerable.Range(1,1000).ToList())
{
sw.Start();
var callerName = (memberName);
sw.Stop();
stackTraceTimings += sw.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations ={0}",stackTraceTimings/1000);
}
OUTPUT: Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations =9.48074760000001 输出:在1000次迭代中使用StackFrame检索调用方名称所花费的时间= 9.48074760000001
Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations =21.7074064 在1000次迭代中使用callerInfo属性检索呼叫者姓名所花费的时间= 21.7074064
Did I misunderstood anything ? 我有误会什么吗? Using
CallerInfo
attributes is the preferred approach right ? 使用
CallerInfo
属性是首选方法,对吗?
Thanks to the below answer for pointing out. 感谢以下答案指出。
I have to re-start the timer every time in the loop. 我必须在循环中每次重新启动计时器。
So, who wins ? 那么,谁赢了? As the below answer says,
CallerInfo
. 如下所示,
CallerInfo
。 Because, it is a compile-time feature and is faster. 因为,这是一个编译时功能,并且速度更快。
Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations =0.00762619999999992 在1000次迭代中使用StackFrame检索调用者名称所花费的时间= 0.00762619999999992
Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations =0.00639420000000002 1000次迭代中使用callerInfo属性检索呼叫者姓名所花费的时间= 0.00639420000000002
I used the below code (revised) and got the above results. 我使用下面的代码(修订)并获得了上述结果。
public class Program
{
public static void Main(string[] args)
{
Method1();
}
static void Method1([CallerMemberName]string memberName = "")
{
double stackTraceTimings = 0;
var sw = new Stopwatch();
foreach(var item in Enumerable.Range(1,1000).ToList())
{
sw.Start();
var callerName = new StackFrame(1).GetMethod().Name;
sw.Stop();
Console.Write(callerName);
sw.Restart();
stackTraceTimings += sw.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations ={0}",stackTraceTimings/1000);
stackTraceTimings = 0;
foreach(var item in Enumerable.Range(1,1000).ToList())
{
sw.Start();
var callerName = (memberName);
Console.Write(callerName);
sw.Stop();
sw.Restart();
stackTraceTimings += sw.Elapsed.TotalMilliseconds;
}
Console.WriteLine("Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations ={0}",stackTraceTimings/1000);
}
}
You have to reset timer before second loop. 您必须在第二个循环之前重置计时器。
sw.Start
starts Stopwatch
from state it was after first loop, so second result is actually time for both StackTrace and Attribute-based solutions summed together. sw.Start
从第一次循环后的状态启动Stopwatch
,因此第二个结果实际上是将StackTrace和基于属性的解决方案加在一起的时间。
CallerMethodName
is compile-type feature, it should definitely be faster. CallerMethodName
是编译类型的功能,它绝对应该更快。
With fixed code timing for CallerMethodName
from your results is: 使用来自您的结果的
CallerMethodName
固定代码计时是:
21.7074064 - (9.48074760000001 * 2) = 2.7459111999999806 21.7074064-(9.48074760000001 * 2)= 2.7459111999999806
That's much faster, isn't it? 那要快得多,不是吗?
subtracted first time twice: once for lack of Reset
call and once for +=
instead of =
. 第一次减去两次:一次是因为缺少
Reset
调用,一次是因为+=
而不是=
。
Update 更新
These results seems to be much too big. 这些结果似乎太大了。 Are you sure you're using Release build, run from outside Visual Studio?
您确定使用从Visual Studio外部运行的Release版本吗? I think not, because otherwise you'd get exact same results for both:
callerName
is never used and will probably be optimized to no-op (at least for second case). 我认为不会,因为否则您会得到完全相同的结果:永远不会使用
callerName
并且可能会将其优化为无操作(至少在第二种情况下)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.