从字符串解析数字的性能
前两天参加公司组织的topcoder编程比赛。其中遇到从字符串中读取整型数字的问题。身边的同事有两个在这里卡了壳。因为时间紧张,我就简单的把自己的实现扔了过去。
/* query format: number1,number2 */
void ReadQuery(std::string& query, int64_t *userid, int16_t * cateid) {
char * endptr = NULL;
*userid = strtoll(query.c_str(), &endptr, 10);
*cateid = (int16_t) atoi(endptr + 1);
}
中间休息去卫生间的路上,想起来如果自己实现这个,有没有可能比使用函数库更快一些呢?自己实现也简单:
void ReadQuery(std::string& query, int64_t *userid, int16_t * cateid) {
int8_t k;
*userid = 0;
*cateid = 0;
const char * p = query.c_str();
while ((k = *p++) != ',') {
*userid = (*userid << 3) + (*userid << 1) + k - '0';
}
while ((k = *p++) != '\0') {
*cateid = (*cateid << 3) + (*cateid << 1) + k - '0';
}
}
还有一种方法,利用sscanf实现:
void ReadQuery(std::string& query, int64_t * userid, int16_t * cateid) {
return sscanf(p, "%lld,%d", a, b);
}
因为是比赛性能嘛,所以把自己能想到的各种奇淫技巧都用上了。事后想想,函数库的实现方式,估计也自己的实现差不多。先不看函数库实现,自己用一些数据测试了一下三者的耗时差异。
300000输入数据,三种方法各跑300遍,得到耗时数据后用Excel画了折线图:
图中去掉了一些规律的高峰值。不明白这些规律的高峰值是什么原因导致的。先记录在此,以后探究。
图中系列1是使用strtoll的实现,系列2是自己逐个字符解析的实现,系列3是利用sscanf的实现。看来strtoll和sscanf的实现性能相近,且比自己的实现要好。后续学习一下库函数是如何实现的。