我正在研究非常大的c ++项目,它具有许多实时关键功能以及许多慢速后台功能.不应从时间关键函数中调用这些后台函数.那么有没有办法检测从关键函数调用的这些后台函数?编译时间会很好,但无论如何我想在这些后台函数之前检测.更多信息,慢速和关键功能都是同一类的一部分,并共享相同的标题.
更多信息,关键函数在非常快的线程(> = 10KHz)下运行较慢,在不同的较慢线程(<= 1KHz)下运行.使用慢函数中的关键部分来保护类成员变量,因为它们都使用相同的类成员变量.这就是在关键功能中调用缓慢功能的原因会降低整体系统性能.这就是我想自动找到所有这些功能而不是手动检查的原因.
谢谢....
获得除尼古拉斯·威尔逊提出的编译时检测之外的编译时检测即使不是不可能,也是极其困难的,但假设“背景”确实指的是函数,而不是多个线程(我在问题中没有看到线程的提及,所以我认为这只是一个奇怪的措辞)您可以简单地使用全局标志和储物柜对象,并且或者assert抛出异常。或者,输出调试消息。当然,这只是运行时的——但是您应该能够非常快速地隔离违规者。对于调试版本来说,它的开销也非常低(几乎保证从 L1 缓存运行),而对于发布版本来说则没有。
使用CaptureStackBackTrace,人们应该能够捕获有问题的函数的地址,类似的工具addr2line(或任何 MS 等效工具)可以直接将其转换为代码中的一行。甚至可能有一个 toolhelp 函数可以直接进行此翻译(尽管我不知道)。
所以,像这样的东西(未经测试!)可能会起作用:
namespace global { int slow_flag = 0; }
struct slow_func_locker
{
slow_func_locker() { ++global::slow_flag; }
~slow_func_locker(){ --global::slow_flag; }
};
#indef NDEBUG
#define REALTIME if(global::slow_flag) \
{ \
void* backtrace; \
CaptureStackBackTrace(0, 1, &backtrace, 0); \
printf("RT function %s called from %08x\n", __FUNCTION__, backtrace); \
}
#define SLOW_FUNC slow_func_locker slow_func_locker_;
#else
#define REALTIME
#define SLOW_FUNC
#endif
foo_class::some_realtime_function(...)
{
REALTIME;
//...
};
foo_class::some_slow_function(...)
{
SLOW_FUNC;
//...
some_realtime_function(blah); // this will trigger
};
Run Code Online (Sandbox Code Playgroud)
唯一真正的缺点(除了不是编译时)是你必须用任一标记来标记每个慢速和实时函数,但由于编译器无法神奇地知道哪个是什么,所以无论如何都没有太多选择。
请注意,全局“标志”实际上是一个计数器,而不是标志。原因是慢速函数可以立即调用另一个返回并清除标志的慢速函数——现在错误地假设一个快速函数(xgbi 建议的临界区方法在这种情况下可能会死锁!)。计数器可以防止这种情况发生。在存在线程的情况下,也可以替换int为std::atomic_int。
编辑:
现在很明显,确实有2 个线程在运行,并且其中一个线程(“快”线程)永远不会调用“慢”函数,这很重要,还有另一个简单的、有效的解决方案(例如使用Win32 API,但也可以使用 POSIX 来完成):
当“快”线程启动时(“慢”线程不需要这样做),将线程 ID 存储在某处,可以是全局变量,也可以是包含所有快/慢函数的对象的成员——任何地方在哪里可以访问:
global::fast_thread_id = GetCurrentThreadId();
Run Code Online (Sandbox Code Playgroud)
用于摆脱“不受欢迎的”函数调用的宏可能如下所示:
#define CHECK_FAST_THREAD assert(GetCurrentThreadID() != global::fast_thread_id)
Run Code Online (Sandbox Code Playgroud)
然后将该宏添加到任何不应从“快”线程调用的“慢”函数中。如果快速线程调用了一个它不能调用的函数,则断言会触发,并且知道哪个函数被调用。
| 归档时间: |
|
| 查看次数: |
271 次 |
| 最近记录: |