c++ - 在编译时进行字符串实习以进行分析
问题描述
语境
我正在开发一个仪器分析器,它使您能够按字符串命名不同的测量值。例如:
MEASURE_SCOPE(text_rendering_code);
...
MEASURE_SCOPE(password_hashing);
...
MEASURE_START(system_call);
...
MEASURE_STOP(system_call);
宏的定义如下:
#define MEASURE_START(name) save_start_event(get_timestamp(), #name);
#define MEASURE_STOP(name) save_stop_event(get_timestamp(), #name);
#define MEASURE_SCOPE(name) Profiling_Class object##name (#name);
class Profiling_Class{
string name;
Profiling_Class(string name){
this->name = name;
save_start_event(get_timestamp(), name);
}
~Profiling_Class(){save_end_event(get_timestamp(), this->name);}
}
save_start_event
并将save_end_event
时间戳和名称一起放入某个全局缓冲区以供以后使用(导出测量值等)。
问题在于:将测量的名称与测量本身一起保存是非常低效的。MEASURE_START
配对和也需要做很多工作MEASURE_STOP
,因为检查它们的名称是否相同需要字符串比较。一个更好的解决方案是实习字符串,即在某个地方有一些数组来保存所有字符串:
std::vector<string> = {"text_rendering_code", "password_hashing", "system_call"};
并将测量宏中的字符串替换为数组中字符串的索引:
MEASURE_SCOPE(0);
...
MEASURE_SCOPE(1);
...
MEASURE_START(2);
...
MEASURE_STOP(2);
这种方式需要更少的存储空间,并且检查名称是否匹配成为一个简单的整数比较。另一方面,它对用户非常不友好,因为他必须提前知道他想要给出他的测量的名称的索引。
问题
有没有办法保持良好的使用MEASURE_SCOPE(text_rendering_code)
并用更有效的MEASURE_SCOPE(0)
自动替换它?这将需要在编译时构建名称数组,有效地实习字符串。这可能吗?
解决方案
我只能猜测你的意思,因为你没有提供足够的细节,而且它们很重要。
一种可能的方法是使用您自己的生成器生成一些临时 C 或 C++ 代码。请记住,可以生成项目的一些 C 或 C++ 代码(这是一种粗略的形式或元编程;Qt moc、RPCGEN、bison、SWIG是 C++ 或 C 生成器的典型示例,但您可以轻松制作自己的代码,请参见此处; 也许在一些脚本语言的帮助下,如Python、Guile、AWK、...,甚至在 C++ 中),您的构建自动化可以处理这个问题(例如,您的Makefile
.
然后,您可以编写一个非常简单的生成程序,收集代码中所有出现的和MEASURE_SCOPE
宏调用(项目文件)。这对编码非常简单:您可以逐行读取所有文件并查找(etc...) 后跟空格,然后在其中查找。MEASURE_START
MEASURE_STOP
*.cpp
.cpp
MEASURE_SCOPE
(
该生成程序 - 处理您的实习字符串 - 可能会发出一个大的头文件measure-generated.h
,例如
// in generated header
#define MEASURE_POINT_system_call 1
#define MEASURE_POINT_password_hashing 2
(也许你想生成一些大的enum
)
它还会发出一个measure-generated-array.cpp
像
// generated code
const char* measure_array[] = {
NULL,
"system_call",
"password_hashing",
/// etc....
NULL,
};
然后你可以在你的一些标题中
#define MEASURE_SCOPE(X) measure_array[MEASURE_POINT_##X]
另请参阅此。
这将需要在编译时构建名称数组,有效地实习字符串。这可能吗?
是的当然。在您自己的 C++ 生成器中执行此操作,该生成器知道您的所有项目*.cpp
文件,就像我建议的那样。您可以在构建时生成 C++ 文件。
推荐阅读
- google-chrome - 在 chrome 扩展清单中为计时器功能保持持久真实的好主意?
- git - github中的双文件夹图标
- python - TensorFlow:如何从 TFHub 模块制作推理图?
- javascript - Apex 图表范围栏颜色
- java - 什么是 vm 参数中的 -D 它表明了为什么我们必须在 vm 参数中始终指定 -D
- xslt - 关于 xsl:try xsl:catch 中的错误信息的问题
- r - 在 R 中,有没有办法减少连续日期 x 轴上的刻度数?
- python - 错误列表索引必须是整数,但只要我不使用输入来获取参数它就可以工作
- html - 如何使用 CSS 为整个 HTML 网页设置字体大小?
- javascript - 如何保存和恢复相机配置