首页   注册   登录

skinny

V2EX 第 118191 号会员,加入于 2015-05-22 10:33:20 +08:00
今日活跃度排名 1716
skinny 最近回复了
6 小时 5 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
自己立一个靶子来攻击,然后我反驳就说我是杠精,也没谁了,你们爱怎么看怎么看吧。

最后:
https://stackoverflow.com/a/30316760
6 小时 10 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@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();
}
}
}
```
9 小时 37 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@lihongjie0209 追加里再次那么细致的说了数据类型、大小、数量、结构,眼神不好?你要不然按#28 楼说的用 range 生成一批数据测试,也没人说你,是不?
9 小时 39 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@hahastudio 刚刚验证了你发的那个链接,按那个解决方法试了,结果还是一样。实际上就是太多小对象,Python 对象底层数据结构又比较大。
9 小时 57 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@laike9m 实际是用 C 根本没问题,顶天了 600MB 左右(粗糙 dict 实现),因为实际数据才 400MB 左右,我吐槽的是内存占用,我根本不在乎快到几分钟内完成,只要在半小时内搞定,不影响我同时在进行的编码任务就行,只要不是过高的 CPU 使用率或是内存占用高到导致其它操作(如编码)不能正常进行就行。一开始我是觉得没问题才这样做的,要是考虑算法,我干嘛用 collections.Counter。
10 小时 11 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@hahastudio 我知道高级语言会比 C 之类占用更多内存,我没有觉得有什么,一开始有心理准备,我粗糙的设计了下 C 的数据结构,预估了内存占用,然后看 pickle 文件和实际数据都不大,全部变成 Python 对象 collections.Counter[str, int]应该可以接受几倍的内存占用,当时我觉得 3GB 到 4GB 内存是可以搞定的,结果没想到爆了。我有考虑不周和偷懒的问题不存在,甚至还有穷的问题存在,不过一些人不知道他们到底在 diss 什么。
10 小时 27 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@nooper 下次遇到相同问题用这个。
10 小时 28 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@kernel 我也是第一次遇到。

@zhzer 是该大一些,我主贴里一开始是吐槽大得超过预期,只是一些人立了些莫名其妙的靶子来 diss 我。
11 小时 52 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@kernel 他们不会去试的。
11 小时 53 分钟前
回复了 skinny 创建的主题 Python Python 内存占用也太大了。
@billgreen1 我从头到尾没有问问题,只是就使用体验的吐槽而已。
@wutiantong 你这更加莫名其妙了,从头到尾没有 pickle 什么事情,我主贴里说了,吐槽的是本来不大的数据,载入转换成 Python 对象以后翻了很多翻,究竟是谁沟通能力、理解能力堪忧?
关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1024 人在线   最高记录 3762   ·  
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.1 · 15ms · UTC 17:34 · PVG 01:34 · LAX 10:34 · JFK 13:34
♥ Do have faith in what you're doing.
沪ICP备16043287号-1