Python:为什么这些脚本在一段时间后变得很慢?

时间:2015-02-04 08:50:52

标签: python performance dictionary

我运行以下脚本从文件f中提取文件g中的域的IP地址。值得一提的是,它们是路径中的11个文件,每个文件大约有8亿行(每个文件f)。在这个脚本中我将文件g加载到内存中的字典d中然后我将文件f的行与字典d中的项目进行比较,如果有,我检查d中的bl_date是否在f之间的日期之间,然后把它写到另一个字典dns_dic。以下是我的脚本的样子:

path = '/data/data/2014*.M.mtbl.A.1'

def process_file(file):
    start = time()
    dns_dic=defaultdict(set)
    d = defaultdict(set)
    filename =file.split('/')[-1]
    print(file)
    g = open ('/data/data/ap2014-2dom.txt','r')
    for line in g:
        line = line.strip('\n')
        domain, bl_date= line.split('|')
        bl_date = int(bl_date)
        if domain in d:
            d[domain].add(bl_date)
        else:
            d[domain] = set([bl_date])

    print("loaded APWG in %.fs" % (time()-start))
    stat_d, stat_dt = 0, 0

    f = open(file,'r')
    with open ('/data/data/overlap_last_%s.txt' % filename,'a') as w:
        for n, line in enumerate(f):
            line=line.strip('')
            try:
                jdata = json.loads(line)
                dom = jdata.get('bailiwick')[:-1]
            except:
                pass
            if dom in d:
                stat_d += 1
                for bl_date in d.get(dom):
                    if jdata.get('time_first') <= bl_date <= jdata.get('time_last'):
                        stat_dt += 1
                        dns_dic[dom].update(jdata.get('rdata', []))

        for domain,ips in dns_dic.items():
            for ip in ips:
                w.write('%s|%s\n' % (domain,ip))
                w.flush()


if __name__ == "__main__":
    files_list = glob(path)
    cores = 11
    print("Using %d cores" % cores)
    pp = Pool(processes=cores)
    pp.imap_unordered(process_file, files_list)
    pp.close()
    pp.join()

这是文件f:

{"bailiwick":"ou.ac.","time_last": 1493687431,"time_first": 1393687431,"rdata": ["50.21.180.100"]}
{"bailiwick": "ow.ac.","time_last": 1395267335,"time_first": 1395267335,"rdata": ["50.21.180.100"]}
{"bailiwick":"ox.ac.","time_last": 1399742959,"time_first": 1393639617,"rdata": ["65.254.35.122", "216.180.224.42"]}

这是文件g:

ou.ac|1407101455
ox.ac|1399553282
ox.ac|1300084462
ox.ac|1400243222

预期结果:

ou.ac|["50.21.180.100"]
ox.ac|["65.254.35.122", "216.180.224.42"]

有人可以帮我找出为什么在某些时候脚本变得非常慢,尽管内存使用时间总是大约400 MG。

1 个答案:

答案 0 :(得分:0)

即使它没有改变整体计算复杂性,我也会从避免冗余的dict查找操作开始。例如,而不是

if domain in d:
    d[domain].add(bl_date)
else:
    d[domain] = set([bl_date])
你可能想做

d.setdefault(domain, set()).add(bl_date)

为了执行一次查找而不是两次。但实际上,set似乎不是存储域访问时间戳的最佳选择。如果您使用了列表,则可以在开始将每个域的时间戳与f的会话数据进行匹配之前对其进行排序。这样,您只需将每个会话的字段time_lasttime_first与域时间戳列表中的第一个和最后一个元素进行比较,以确定是否要放置IP地址进入dns_dic[dom]

通常,您在for bl_date in d.get(dom):循环中执行了大量不必要的工作。至少,在bl_datetime_last字段之间的第一个time_first,您应该终止循环。根据{{​​1}}的长度,这可能是您的瓶颈。