- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在考虑使用类似 StackFrame stackFrame = new StackFrame(1)
的东西来记录执行方法,但我不知道它对性能的影响。堆栈跟踪是在每次方法调用时构建的东西,所以性能不应该是一个问题,还是它只是在被要求时构建的东西?您是否建议在性能非常重要的应用程序中反对它?如果是这样,是否意味着我应该在发布时禁用它?
最佳答案
编辑:一些背景
我们有一个类似的功能,但 99% 的时间都被禁用;我们使用的方法如下:
public void DoSomething()
{
TraceCall(MethodBase.GetCurrentMethod().Name);
// Do Something
}
public void TraceCall(string methodName)
{
if (!loggingEnabled) { return; }
// Log...
}
TraceCall(MethodBase.GetCurrentMethod().Name)
这很简单,但无论是否启用跟踪,我们都会招致使用反射查找方法名称的性能损失。
我们的选择是要么在每个方法中都需要更多代码(并冒简单错误或拒绝的风险),要么切换到使用 StackFrame
来确定调用方法仅记录时已启用。
选项 A:
public void DoSomething()
{
if (loggingEnabled)
{
TraceCall(MethodBase.GetCurrentMethod().Name);
}
// Do Something
}
public void TraceCall(string methodName)
{
if (!loggingEnabled) { return; }
// Log...
}
选项 B:
public void DoSomething()
{
TraceCall();
// Do Something
}
public void TraceCall()
{
if (!loggingEnabled) { return; }
StackFrame stackFrame = new StackFrame(1);
// Log...
}
我们选择了选项 B。与选项 A 相比,它提供了显着的性能改进当禁用日志记录时,99% 的时间并且实现起来非常简单。 p>
这里是对 Michael 代码的修改,以显示这种方法的成本/ yield
using System;
using System.Diagnostics;
using System.Reflection;
namespace ConsoleApplication
{
class Program
{
static bool traceCalls;
static void Main(string[] args)
{
Stopwatch sw;
// warm up
for (int i = 0; i < 100000; i++)
{
TraceCall();
}
// call 100K times, tracing *disabled*, passing method name
sw = Stopwatch.StartNew();
traceCalls = false;
for (int i = 0; i < 100000; i++)
{
TraceCall(MethodBase.GetCurrentMethod());
}
sw.Stop();
Console.WriteLine("Tracing Disabled, passing Method Name: {0}ms"
, sw.ElapsedMilliseconds);
// call 100K times, tracing *enabled*, passing method name
sw = Stopwatch.StartNew();
traceCalls = true;
for (int i = 0; i < 100000; i++)
{
TraceCall(MethodBase.GetCurrentMethod());
}
sw.Stop();
Console.WriteLine("Tracing Enabled, passing Method Name: {0}ms"
, sw.ElapsedMilliseconds);
// call 100K times, tracing *disabled*, determining method name
sw = Stopwatch.StartNew();
traceCalls = false;
for (int i = 0; i < 100000; i++)
{
TraceCall();
}
Console.WriteLine("Tracing Disabled, looking up Method Name: {0}ms"
, sw.ElapsedMilliseconds);
// call 100K times, tracing *enabled*, determining method name
sw = Stopwatch.StartNew();
traceCalls = true;
for (int i = 0; i < 100000; i++)
{
TraceCall();
}
Console.WriteLine("Tracing Enabled, looking up Method Name: {0}ms"
, sw.ElapsedMilliseconds);
Console.ReadKey();
}
private static void TraceCall()
{
if (traceCalls)
{
StackFrame stackFrame = new StackFrame(1);
TraceCall(stackFrame.GetMethod().Name);
}
}
private static void TraceCall(MethodBase method)
{
if (traceCalls)
{
TraceCall(method.Name);
}
}
private static void TraceCall(string methodName)
{
// Write to log
}
}
}
结果:
Tracing Disabled, passing Method Name: 294ms
Tracing Enabled, passing Method Name: 298ms
Tracing Disabled, looking up Method Name: 0ms
Tracing Enabled, looking up Method Name: 1230ms
关于c# - StackFrame 的性能如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1348643/
我编写了一个将输入打印到标准输出的 c 程序。然后我把它转换成汇编语言。顺便说一句,我使用的是 AT&T 语法。 这是简单的 C 代码。 #include int main() { int c;
我正在考虑使用类似 StackFrame stackFrame = new StackFrame(1) 的东西来记录执行方法,但我不知道它对性能的影响。堆栈跟踪是在每次方法调用时构建的东西,所以性能不
我有一个 IEnumerable frames用于存储一些自定义 StackFrame。我想将其转换为 StackTrace.ToString() 之类的字符串类型格式。例如: at TestS
这是我的代码: public class UserPreferences { /// /// The EMail signature. /// [UserPrefe
我在我的 ASP.NET Web 应用程序中使用以下方法来接收异常的堆栈跟踪: public static void getStackTraceInfo(System.Diagnostics.Stac
在我的日志记录模块中有一行: MethodBase methodBase = new StackFrame(2, false).GetMethod(); 我检查的方法是泛型方法,定义为T[] MyMe
我写了一个方法 Assert(): [System.Diagnostics.Conditional("DEBUG")] internal static void Assert(bool conditi
我正在开发一些内部日志记录框架,为了性能起见,懒惰地获取 StackFrame 似乎是个好主意。我想使用此 StackFrame 获取我的日志记录框架之外的第一个方法。 我最初的想法是这样的: usi
写题目的时候碰到的其他一些最相关的帖子...导致 MSDN http://msdn.microsoft.com/en-us/library/system.reflection.parameterinf
目标是根据调用我的方法的类型创建一个通用实例。 问题是,当从泛型调用时,StackFrame 似乎只包含开放定义类型参数,而不是封闭定义类型参数。如何从 StackFrame 获取类型参数?类似于 t
我正在尝试编写一个将信号实现为 xv6 的程序 我已经弄清楚如何操纵堆栈(我认为),但我只是无法恢复它。这是我的信号传递代码: 此函数将信号帧添加到进程堆栈并保存 volatile 寄存器 void
我通过在 StackFrameStream 上使用 walk 方法得到了一个 StackFrames 列表。但我只需要找到前 3 个 stackFrames。 我有 StackFrameStream
目前,我通过 StackFrame 来获取当前文件/行号: Log.Message(new StackFrame(0, true), "FAILED to start cooling."); Log
这其实挺难处理的,有人暗示我这不正常? 我继承了这个项目,所以我想也许在我看不到的地方设置了一个标志 这是我的一个异常(exception)的片段: 27 libswiftCore.dyli
我正在关注 Memory Layout And The Stack理解栈帧.. 作者很好地解释了堆栈帧并说明了在给定时间点堆栈中的内容 他还在下面问了一些问题 假设一个程序进行了 5 次函数调用。堆栈
如果我只是想执行以下操作以查看是什么调用了我, var st = new StackTrace(); var callingMethod = st.GetFrame(1).GetMethod() 只购
我看到在 .NET 中实现登录时使用 StackFrame 和 MethodBase 的两个独立代码。 我知道 MethodBase 类提供有关方法和构造函数及其来源的信息。 StackFrame 表
我是一名优秀的程序员,十分优秀!