python的sorted排序和heapq排序,在排序找出最大项时,有关性能的问题。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
paramiao
V2EX    Python

python的sorted排序和heapq排序,在排序找出最大项时,有关性能的问题。

  •  
  •   paramiao 2013-02-26 13:42:26 +08:00 6452 次点击
    这是一个创建于 4613 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一些数据需要先进行循环统计某些字段重复项,大概需要5次排序,找出5个字段重复项较多的数据,开始时我用的是python的sorted函数,后来发现当数据到百万级别时,单机计算需要以小时为单位了,然后优化时考虑到只取排序后较大数据,就改用最大堆排序,python的heapq模块,结果发现并没优化太多,求解?
    13 条回复    1970-01-01 08:00:00 +08:00
    ThunderEX
        1
    ThunderEX  
       2013-02-26 13:45:13 +08:00
    不是有max()嘛
    phuslu
        2
    phuslu  
       2013-02-26 14:24:07 +08:00
    直接用 collections.Counter 不行吗?
    paramiao
        3
    paramiao  
    OP
       2013-02-26 14:43:39 +08:00
    @ThunderEX max不是最大的一个数据吗?我需要的是100万中最大的50个
    paramiao
        4
    paramiao  
    OP
       2013-02-26 15:01:55 +08:00
    @phuslu 主要是元数据结构比较复杂,不是单纯的list or dict,是比较复杂的json数据,所以需要自己去count然后sort,如果转的话也行但是会造成内存空间占用比较大,因为冗余字段会变多
    keakon
        5
    keakon  
       2013-02-26 15:09:16 +08:00
    @paramiao heapq.nlargest()

    你最好 cProfile 一下看看瓶颈在哪。有次我把 nlargest() 和 sorted() 来比较,发现用的时间基本没差别。最后看了下排序的时间分别为 0.001 和 0.003 秒,而 IO 和其他计算时间是超过 1 秒的,当然看不出差距…
    paramiao
        6
    paramiao  
    OP
       2013-02-26 15:35:28 +08:00
    @keakon 我和你说的情况一样,不过我统计的没有包括IO和其他计算,所以我总觉得是heapq的实现问题,heapq是不是本身就是通过python实现的,没有原生C写的排序性能好呢?
    phuslu
        7
    phuslu  
       2013-02-26 15:42:28 +08:00   2
    @paramiao heapq.nlargest 不要传 key 参数. 传了话就是用 pure python 代码来排序。
    你可以实现 __cmp__, 然后调用试下 :D
    brucexin
        8
    brucexin  
       2013-02-26 16:59:55 +08:00
    不能从原数据构造出索引吗?
    paramiao
        9
    paramiao  
    OP
       2013-02-26 17:09:36 +08:00
    @brucexin 可以啊,一般排序通过key都可以使用,但是问题是构造索引时,其他的属性或字段不能扔掉,因为数据比较大,这样占用内存会很大
    jk2r
        10
    jk2r  
       2013-02-26 19:01:50 +08:00
    首先,heapq确实是用python写的。如果5个字段都分别存入,这个消耗确实很大(冗余)。
    建议先time python *.py调试一下代码,看看主要耗时在哪。
    索引可以这样做:原文一个key-value,5个字段分别存5个key(hash字段)-list(count,原文key数组)。这样可以保证,500万的数据只有一次线性扫描,扫描过程中,解json串存k-list。
    我这边测试,会快很多。
    keakon
        11
    keakon  
       2013-2-26 21:36:36 +08:00   1
    @jk2r 是有C版本的哦
    >>> import _heapq
    >>> dir(_heapq)
    ['__about__', '__doc__', '__file__', '__name__', '__package__', 'heapify', 'heappop', 'heappush', 'heappushpop', 'heapreplace', 'nlargest', 'nsmallest']
    >>> _heapq.__file__
    '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_heapq.so'
    Parallel
        12
    Parallel  
       2013-03-08 18:20:35 +08:00
    python的堆排肯定不如C或C++的快啊。。
    自己敲一个堆排试试。。
    Parallel
        13
    Parallel  
       2013-03-08 18:23:25 +08:00
    另外堆排的最坏时间复杂度是nlog(n)呐。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2791 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 14:50 PVG 22:50 LAX 07:50 JFK 10:50
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86