我必须阅读大约300个文件来创建与以下代码段的关联。鉴于这种关联,我必须在内存中阅读它们。
with util.open_input_file(f) as f_in:
for l in f_in:
w = l.split(',')
dfm = dk.to_key((idx, i, int(w[0]), int(w[1]))) <-- guaranteed to be unique for each line in file.
cands = w[2].split(':')
for cand in cands:
tmp_data.setdefault(cand, []).append(dfm)
然后我需要以这种格式写出上面的数据结构:
k1, v1:v2,v3....
k2, v2:v5,v6...
我使用以下代码:
# Sort / join values.
cand2dfm_data = {}
for k,v in tmp_data.items():
cand2dfm_data[k] = ':'.join(map(str, sorted(v, key=int)))
tmp_data = {}
# Write cand2dfm CSV file.
with util.open_output_file(cand2dfm_file) as f_out:
for k in sorted(cand2dfm_data.keys()):
f_out.write('%s,%s\n' % (k, cand2dfm_data[k]))
由于我必须处理大量文件,因此我发现了两个问题:
用于存储 tmp_data 的内存非常大。在我的用例中,处理300个文件,它使用的是42GB。
写出CSV文件需要很长时间。这是因为我在每个item()上调用write()(大约2.2M)。此外,输出流使用gzip压缩器来节省磁盘空间。
在我的用例中,数字保证是32位无符号。
问题:
为了减少内存,我认为最好使用32位的int来存储数据。我应该使用ctypes.c_int()将值存储在dict()中(现在它们是字符串)还是有更好的方法?
为了加快写入速度,我应该写一个StringIO对象然后将其转储到文件中还是有更好的方法?
或者,也许有更好的方法可以在不读取内存中的所有内容的情况下完成上述逻辑?
答案 0 :(得分:2)
几点想法。
目前,您在内存中多次复制数据。
您是第一次将其加载到tmp_data
,然后将所有内容复制到cand2dfm_data
,然后通过调用sorted(cand2dfm_data.keys())
创建密钥列表。
减少内存使用量:
摆脱tmp_data
,解析并直接将数据写入cand2dfm_data
让cand2dfm_data
列出元组列表,而不是字典
使用cand2dfm_data.sort(...)
代替sorted(cand2dfm_data)
以避免创建新列表
加快处理速度:
将密钥转换为整数以提高排序性能(这也会减少内存使用量)
将数据一次性写入磁盘,例如100或500或1000条记录,这样可以提高I \ O性能
使用profiler查找其他效果瓶颈
如果使用上述优化,内存占用仍然太大,则考虑使用磁盘备份存储来存储和排序临时数据,例如: SQLite