@
wutiantong 你也可以完全不用 pickle 来测试,测试数据你可以简单先生成 3000 万条长度为 3-32 的 ascii printable 字符串(我这最长的一条有 95 个字节,不过非常非常少,多是 6 到 12 个字节的),重复数据条数占 24%,重复数据你随机插入,生成的字符串作为 K,V 你可以随机产生 1 到 2000 万之间的值,,生成测试数据要花时间,你也可以用更好的办法。
说实在的,我一开始就是吐槽 Python 对象内存占用大。
为了避免有人硬说内存泄露,你可以用如下代码(结果一样,内存需要非常多):
```python
# Version: Python 3.6.6 x64
import collections
import glob
counter = collections.Counter()
# 你也可以直接用 dict
# counter = dict()
for path in glob.glob(r'F:\TestData\*.txt'):
with open(path, encoding='UTF-8') as input_stream:
for line in input_stream:
tmp = line.rstrip()
k, v = tmp.rsplit('\t', maxsplit=1)
c = int(v)
del v
del tmp
counter[k] += c
# n = counter.get(k, 0)
# counter[k] = c + n
```
我用.net core 按相似的方法实现了一遍,速度很快,内存占用 3GB:
```c#
// .net core 2.1
//
// Program.cs build options: Release, x64
using System;
using System.Collections.Generic;
using
System.IO;
using System.Text;
namespace db_conv_cs
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, uint> counter = new Dictionary<string, uint>();
string[] files = new string[]
{
@"F:\TestData\dat-1.txt",
@"F:\TestData\dat-2.txt",
@"F:\TestData\dat-3.txt",
@"F:\TestData\dat-4.txt",
@"F:\TestData\dat-5.txt"
};
foreach (string path in files)
{
InsertItems(path, counter);
}
Console.WriteLine("{0} items", counter.Count);
}
static void InsertItems(string path, Dictionary<string, uint> counter)
{
FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(file, Encoding.UTF8);
string line = null;
while ((line = reader.ReadLine()) != null)
{
line = line.TrimEnd('\r', '\n');
int i = line.LastIndexOf('\t');
if (i == 0)
{
continue;
}
string k = line.Substring(0, i);
string v = line.Substring(i + 1);
uint n = uint.Parse(v);
uint c = 0;
counter.TryGetValue(k, out c);
counter[k] = c + n;
}
reader.Close();
file.Close();
}
}
}
```