如题,本来想写个小程序,对比一下 c++,python,golang 处理日志文件的效率。找了个 600MB 的日志文件试水,结果因为本人水平有限,导致 c++的实现出现了大量的内存消耗,运行不完就被 kill 了。
程序的思路是逐行读取日志文件,用空格切分,第一个字段作为 key,剩下的字段去重后作为 value。
先贴一下 python 的实现
big_dict = {}
with open("data/test_log.txt") as f_in:
for line in f_in:
items = line.strip().split(' ')
key = items[0]
if key not in big_dict:
big_dict[key] = set([])
for i in items[1:]:
big_dict[key].add(i)
print "total keys:", len(big_dict)
再贴一下 golang 的:
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
)
func process(fname string, big_dict map[string]map[string]int) {
fin, err := os.Open(fname)
defer fin.Close()
if err != nil {
fmt.Println("Open file error ", err)
return
}
buf := bufio.NewReader(fin)
line_count := 0
for ; ; line_count++ {
line, err := buf.ReadString('\n')
if err != nil {
if io.EOF == err {
break
}
fmt.Println("Error in ReadBytes: ", err)
return
}
items := strings.Split(line, " ")
key := items[0]
elem, ok := big_dict[key]
if false == ok {
big_dict[key] = make(map[string]int)
}
elem = big_dict[key]
for i := 1; i < len(items); i++ {
elem[items[i]] = 1
}
}
fmt.Println("Total Line Count: ", line_count)
}
func main() {
const fname = "data/test_log.txt"
big_dict := make(map[string]map[string]int)
process(fname, big_dict)
fmt.Println("Total Key Count: ", len(big_dict))
}
最后贴一下 c++的。
#include <iostream>
#include <fstream>
#include <string>
#include<unordered_map>
#include<unordered_set>
using namespace std;
// data/test_log.txt 文件是一个 600MB 的日志文件
const string IN_FNAME = "data/test_log.txt";
unordered_map<string, unordered_set<string *>* > big_dict;
void process_file(const string fname, unordered_map<string,unordered_set<string*> *> & big_dict) {
ifstream f_in;
f_in.open(fname, ios::in);
string line = "";
int total_line = 0;
size_t start =0, end = 0;
while(getline(f_in, line)) {
++total_line;
start =0, end = 0;// c++没有内建 string 的分割,自己 diy 个
end = line.find_first_of(' ',start);
string key = line.substr(start,end);
// 寻找是否存在 key
if(big_dict.find(key) == big_dict.end()) {
unordered_set<string*> *p = new unordered_set<string*>;
big_dict[key] = p;
}
start = end+1;
while(start<line.size()) {
end = line.find_first_of(' ',start);
if(string::npos == end) end = line.size() - 1;
string value = line.substr(start,end);
big_dict[key]->insert(&value);//大部分的时间都在这个 insert 上了
//这里我存的是 string 的指针,实际上无法得到去重的效果
//但是我如果直接存 string 对象,会直接爆内存
start = end + 1;
}
}
f_in.close();
}
int main() {
process_file(IN_FNAME, big_dict);
cout<<"Total Keys:"<<big_dict.size()<<endl;
return 0;
}
c++的实现中,big_dict[key]->insert(&value);
大部分的时间都在这个 insert 上了,这里我存的是 string 的指针,实际上无法得到去重的效果。但是我如果直接存 string 对象,会直接爆内存。我存指针可以解决内存的问题,但是执行速度上依然是 go 快过 python,最慢的是 c++。
希望有大神能指点下,看我的 c++代码哪里出了问题。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.