如何解决极慢的 char* 访问
编辑:解决方案
我没有使用查找表,而是能够对值进行分组,这样我就可以使用一系列条件来选择值。
原来的 3.702663s 现在变成了 1.630996。
在 switch 语句中使用范围更进一步,性能提高了 3.759549s -> 1.013868s(提高了 3.7 倍)
不清楚为什么查找表会导致延迟,但希望我能解决这个问题,因为我更喜欢这个表。
也许我已经看过太多次了,或者我忽略了一些非常愚蠢的东西,但无论我改变什么,我都会遇到同样的问题。问题是访问 buffer
应该是常数时间,但是如果我使用变量 third
而不是 first
作为 table
中的索引,它需要几乎两倍的时间处理文件。它发生在任何大小的文件中。
(test.txt 可以通过用字节
1GB 文件的时间。
$ gcc -O2 -o test test.c && ./test && rm test
2.0287s
3.7871s
有什么想法吗?
(我写这个是为了证明这个问题,是的,除此之外它毫无用处)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static const uint8_t table[64] = {
1,1,};
#define RUN(variable) \
idx = 0; \
first = buffer[idx]; \
second = buffer[idx]; \
next = idx + table[second]; \
third = buffer[next]; \
start = clock(); \
while (idx < length) { \
first = second; \
second = third; \
idx = next; \
next += table[variable]; \
third = (next < length) ? (buffer[next]) : 0; \
} \
end = clock(); \
printf("%fs\n",(float)(end - start) / CLOCKS_PER_SEC);
int main() {
uint8_t first,second,third;
size_t idx,next,length;
clock_t start,end;
FILE* file = fopen("test.txt","rb");
fseek(file,SEEK_END);
length = ftell(file);
rewind(file);
char* buffer;
buffer = (char*)malloc(sizeof(char) * length);
fread(buffer,length,file);
fclose(file);
RUN(first);
RUN(third);
free(buffer);
return 0;
}
编辑:没有宏,单独的开始/结束
gcc -O2 -o test test.c && ./test && rm test
1.9776s
3.6817s
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static const uint8_t table[64] = {
1,};
int main() {
uint8_t first,result,length;
clock_t start1,end1,start2,end2;
FILE* file = fopen("test.txt",file);
fclose(file);
// Using variable 'first' and {start,end}1
idx = 0;
first = buffer[idx];
second = buffer[idx];
next = idx + table[second];
third = buffer[next];
start1 = clock();
while (idx < length) {
first = second;
second = third;
idx = next;
next += table[first];
third = (next < length) ? (buffer[next]) : 0;
}
end1 = clock();
printf("%fs\n",(float)(end1 - start1) / CLOCKS_PER_SEC);
// Using variable 'third' and {start,end}2
idx = 0;
first = buffer[idx];
second = buffer[idx];
next = idx + table[second];
third = buffer[next];
start2 = clock();
while (idx < length) {
first = second;
second = third;
idx = next;
next += table[third];
third = (next < length) ? (buffer[next]) : 0;
}
end2 = clock();
printf("%fs\n",(float)(end2 - start2) / CLOCKS_PER_SEC);
free(buffer);
return 0;
}
解决方法
在线:
third = (next < length) ? (buffer[next]) : 0;
// 1 < 64 ? 64 : 0;
在第一遍的示例中,第三个 = 64 在下一个循环中转到表数组之外:
next += table[third]; // table[64]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。