Context
I am working on an instrumenting profiler, that enables you to name different measurements by string. So for example:
MEASURE_SCOPE(text_rendering_code);
...
MEASURE_SCOPE(password_hashing);
...
MEASURE_START(system_call);
...
MEASURE_STOP(system_call);
where the macros would be defined like this:
#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
and save_end_event
would just put the timestamp along with the name into some global buffer for later use (exporting measurements and such).
The problem is this: saving the name of a measurement along with the measurement itself is very inefficient. There also needs to happen a lot of work to pair MEASURE_START
and MEASURE_STOP
, because checking if their names are same requires a string-compare. A much better solution would be to intern the string, i.e. have some array somewhere that holds all the strings:
std::vector<string> = {"text_rendering_code", "password_hashing", "system_call"};
and substitue the string in the measurement-macros with the index of the string in the array:
MEASURE_SCOPE(0);
...
MEASURE_SCOPE(1);
...
MEASURE_START(2);
...
MEASURE_STOP(2);
This way requires less storage, and checking if names match becomes a simple integer-compare. On the other hand, it's very unfriendly towards the user, since he has to know in advance the index of the name he wants to give his measurement.
Question
Is there a way to preserve the nice usage of MEASURE_SCOPE(text_rendering_code)
and substitute this with the more efficient MEASURE_SCOPE(0)
automatically? This would require building the name-array at compile time, effectively interning the strings. Is this possible?