我有一个大小为 1024^3 (1G) 的 char* buf。它包含换行符分隔的十六进制数字 ( 7fefdfff7\n7fefdfff8\n7fefdfff9\n7fefdfff\n7fefdfffb),我正在尝试读取和解析它们中的每一个。
我的第一种方法是:
int buf_length = 1024 * 1024 * 1024;
char *buf = new char[buf_length];
std::size_t numchars = 0;
for (int offset = 0; offset <buf_length; offset += numchars) {
unsigned long tmp = std::stoul(&buf[offset], &numchars, 16);
process(tmp);
}
Run Code Online (Sandbox Code Playgroud)
但是循环的每次迭代都花费了异常长的时间。一旦我切换到以下内容,它的速度要快得多:
int buf_length = 1024 * 1024 * 1024;
char *buf = new char[buf_length];
std::size_t numchars = 0;
for (int offset = 0; offset <buf_length; offset += numchars) {
// omitting size of the string below does not affect performance much
std::string s(buf, 9);
unsigned long tmp = std::stoul(s, &numchars, 16);
process(tmp);
}
Run Code Online (Sandbox Code Playgroud)
似乎在第一种情况下 stoul() 每次都处理到缓冲区结束,但无法解释原因。你能帮我理解这里发生了什么,为什么两种情况下的性能如此不同?
std::stoul需要一个const std::string&而不是一个const char*。这意味着 astd::string是从以空字符结尾的字符串构造的,需要复制每个字符。
您可以改为使用std::strtoulwhichconst char*直接接受参数:
for (const char* ptr = buf; ptr < buf + buf_length;) {
unsigned long tmp = std::stroul(ptr, &ptr, 16);
process(tmp);
}
Run Code Online (Sandbox Code Playgroud)