gpt4 book ai didi

c# - 获取特定的 StackFrame 而不是 StackTrace.GetFrame 是否更便宜?

转载 作者:可可西里 更新时间:2023-11-01 09:11:53 35 4
gpt4 key购买 nike

如果我只是想执行以下操作以查看是什么调用了我,

var st = new StackTrace();
var callingMethod = st.GetFrame(1).GetMethod()

只购买那个特定的框架会更便宜吗?

var sf = new StackFrame(1);
var callingMethod = sf.GetMethod()

我用下面的代码进行了测试,但我不确定我的方法是否合理。


Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
var method = new StackFrame(1, false);
}
sw.Stop();
Trace.WriteLine(sw.ElapsedMilliseconds);

sw = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
var method = new StackTrace().GetFrame(1);
}
sw.Stop();
Trace.WriteLine(sw.ElapsedMilliseconds);

// Results
// StackFrame: 850
// StackTrace: 1334

我的方法(和结果)是否正确?

编辑

我会使用 Caller Information属性,但是,我暂时停留在 .NET 3.5 中。

最佳答案

参见 recommendations为编译正确的基准。您应该使用质数迭代(用于抑制 JIT Loop unwinding 优化),在 Release模式下运行基准测试而不调试,使用缓存预热等。

我在 BenchmarkDotNet 中添加了您的示例,看StackFrameProgram.cs :

public class StackFrameProgram
{
private const int IterationCount = 100001;

public void Run()
{
var competition = new BenchmarkCompetition();
competition.AddTask("StackFrame", () => StackFrame());
competition.AddTask("StackTrace", () => StackTrace());
competition.Run();
}

private StackFrame StackFrame()
{
StackFrame method = null;
for (int i = 0; i < IterationCount; i++)
method = new StackFrame(1, false);
return method;
}

private StackFrame StackTrace()
{
StackFrame method = null;
for (int i = 0; i < IterationCount; i++)
method = new StackTrace().GetFrame(1);
return method;
}
}

这是我的结果(Intel Core i7-3632QM CPU 2.20GHz):

x86, .NET 3.5:
StackFrame : 1035ms
StackTrace : 1619ms

x64, .NET 3.5:
StackFrame : 981ms
StackTrace : 1754ms

x86, .NET 4.0:
StackFrame : 735ms
StackTrace : 1150ms

x64, .NET 4.0:
StackFrame : 637ms
StackTrace : 880ms

让我们看看里面:

public StackFrame.ctor(int skipFrames, bool fNeedFileInfo)
{
this.InitMembers();
this.BuildStackFrame(skipFrames, fNeedFileInfo);
}

private void StackFrame.BuildStackFrame(int skipFrames, bool fNeedFileInfo)
{
StackFrameHelper sfh = new StackFrameHelper(fNeedFileInfo, null);
StackTrace.GetStackFramesInternal(sfh, 0, null);
int numberOfFrames = sfh.GetNumberOfFrames();
skipFrames += StackTrace.CalculateFramesToSkip(sfh, numberOfFrames);
if ((numberOfFrames - skipFrames) > 0)
{
this.method = sfh.GetMethodBase(skipFrames);
this.offset = sfh.GetOffset(skipFrames);
this.ILOffset = sfh.GetILOffset(skipFrames);
if (fNeedFileInfo)
{
this.strFileName = sfh.GetFilename(skipFrames);
this.iLineNumber = sfh.GetLineNumber(skipFrames);
this.iColumnNumber = sfh.GetColumnNumber(skipFrames);
}
}
}

public StackTrace.ctor()
{
this.m_iNumOfFrames = 0;
this.m_iMethodsToSkip = 0;
this.CaptureStackTrace(0, false, null, null);
}

private void StackTrace.CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThread, Exception e)
{
this.m_iMethodsToSkip += iSkip;
StackFrameHelper sfh = new StackFrameHelper(fNeedFileInfo, targetThread);
GetStackFramesInternal(sfh, 0, e);
this.m_iNumOfFrames = sfh.GetNumberOfFrames();
if (this.m_iMethodsToSkip > this.m_iNumOfFrames)
{
this.m_iMethodsToSkip = this.m_iNumOfFrames;
}
if (this.m_iNumOfFrames != 0)
{
this.frames = new StackFrame[this.m_iNumOfFrames];
for (int i = 0; i < this.m_iNumOfFrames; i++)
{
bool flag = true;
bool flag2 = true;
StackFrame frame = new StackFrame(flag, flag2);
frame.SetMethodBase(sfh.GetMethodBase(i));
frame.SetOffset(sfh.GetOffset(i));
frame.SetILOffset(sfh.GetILOffset(i));
frame.SetIsLastFrameFromForeignExceptionStackTrace(sfh.IsLastFrameFromForeignExceptionStackTrace(i));
if (fNeedFileInfo)
{
frame.SetFileName(sfh.GetFilename(i));
frame.SetLineNumber(sfh.GetLineNumber(i));
frame.SetColumnNumber(sfh.GetColumnNumber(i));
}
this.frames[i] = frame;
}
if (e == null)
{
this.m_iMethodsToSkip += CalculateFramesToSkip(sfh, this.m_iNumOfFrames);
}
this.m_iNumOfFrames -= this.m_iMethodsToSkip;
if (this.m_iNumOfFrames < 0)
{
this.m_iNumOfFrames = 0;
}
}
else
{
this.frames = null;
}
}

public virtual StackFrame StackTrace.GetFrame(int index)
{
if (((this.frames != null) && (index < this.m_iNumOfFrames)) && (index >= 0))
{
return this.frames[index + this.m_iMethodsToSkip];
}
return null;
}

关于c# - 获取特定的 StackFrame 而不是 StackTrace.GetFrame 是否更便宜?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18836773/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com