Tinyfool@Csdn

天行健,君子以自强不息----本Blog内容均可转载,但是作者不放弃版权,转载必须标明作者和原文地址。

郝培强ID:tinydust
178442次访问,排名381好友0人,关注者6
tinydust的文章
原创 43 篇
翻译 6 篇
转载 0 篇
评论 505 篇
Tinyfool的公告
CodeChina.Org 中国代码网-中国程序员的代码天堂

银杏泰克科技有限公司[站内搜索解决方案]

全能之眼
Tiny同志在配眼镜

微尘程序员网站

最近评论
lao1000:有点意思
renxinzhi:不能光看眼前的蝇头小利,与Google合作雅虎失掉的是继续前行的动力,本来广告是雅虎的主业,现在(相当于)把广告卖给Google,连雅虎都失去了对自己的信心,那么怎么让广告客户对它坚定信心呢?由于Google与雅虎是天生的竞争对手,而且Google又在合作中占据强势地位,对两者来说是此消彼长的关系,但是肯定是Google上涨。这样不仅会造成雅虎的客户流失,而且也使由于暂时的获利雅虎失去了继续……
bad__ba:个人觉得如果Google耗巨资来制作系统和应用软件的话,也不会只靠广告来收入,软件收费几乎是必然的。
tinydust::)
turingbook:很精辟。Google的本质是一家广告公司,终端用户免费,找商家要钱,认识这一点非常重要。这也是微软、诺基亚甚至英国电信都害怕Google的原因。如果Google把这种模式推广到操作系统、Office、手机乃至接入,使用全部免费,只靠广告买单,什么微软、诺基亚和英国电信岂不是都完蛋了么?
文章分类
收藏
    相册
    ATinyGBA
    blog用图
    China Mdc2004
    Tinyfool
    Tinyfool的开发日记(RSS)
    Tinyfool的移动开发阵线(RSS)
    Tinyfool的随想录(RSS)
    微尘程序员网站
    联系Tinyfool
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 一个Python程序的6次改进收藏

    新一篇: Web应用和PC端软件开发的共同趋势是并行 | 旧一篇: 什么是BOINC?

    有位朋友用CString类写了一个Email列表去重程序,结果发现处理78000 行的数据居然用了7分多种。于是他用Python的map(hash实现的)重写了这个程序,最后只用了300ms。CString一定会慢,因为实现中 没有使用hash。于是有人用c写了一个hash函数来实现这个功能,最后花了400ms。但是代码长度是Python代码的数十倍。详情请看这里hashtable功能也实现了这个功能,速度超过了Python,但是代码也很简洁。qyb说,“这个例子再一次教育我们,熟练掌握优秀的第三方库是多么的重要.”

    我这里没有现成的gcc和glib,不好测试qyb的程序。但是仅就那个用来测试Python程序来说,存在很多降低效率的误区,所以,我把这些问题都用效率更加的方式改写了,从而把程序的效率提高了三倍左右,现在与大家分享。

    原程序:运行时间0:00:00.609000
    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    line = f.readline();
    while len(line)>0:
    if not hashtable.has_key(line):
    hashtable[line] = 1
    f2.write(line)
    line = f.readline();
    f.close()
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)


    显而易见,用f.readline()是不明智的,这样输入速度大减。我们用readlines()来加速。
    改进一:运行时间0:00:00.375000
    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    lines = f.readlines()
    for line in lines:
    if not hashtable.has_key(line):
    hashtable[line] = 1
    f2.write(line)
    f.close()
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)

    然 后我们看输出,很显然f2.write(line)也是很不明智的,一行一行的输出无论如何都是低效的。writelines可以解决这个问题,我们知道 map的keys()函数可以返回map的键列表,所以, f2.writelines(hashtable.keys())看来是个好选择。
    改进二:运行时间0:00:00.281000

    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    lines = f.readlines()
    for line in lines:
    if not hashtable.has_key(line):
    hashtable[line] = 1
    f.close()
    f2.writelines(hashtable.keys())
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)

    实际上我们知道采用hashtable[line] = 1方式的时候,如果键已经存在,仅仅会更新键的值而已。所以判断语句if not hashtable.has_key(line)实际上是无用的,应该去掉。
    改进三:运行时间0:00:00.250000

    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    lines = f.readlines()
    for line in lines:
    hashtable[line] = 1
    f.close()
    f2.writelines(hashtable.keys())
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)


    到这里我们发现另外一个问题,我们实际上只需要map的键,而不需要它的值。所以我们直接用操作map的键列表的方式应该可以加速程序的运行。幸好,运行的结果证明了我的推论。
    改进四:运行时间0:00:00.188000

    import datetime
    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    lines = f.readlines()
    for line in lines:
    hashtable.keys().append(line)
    f.close()
    f2.writelines(hashtable.keys())
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)

    然后,我遭遇了一个小挫败,我记得有人告诉过我用map函数处理列表应该比for in方式更加高效。但是运行结果没有遵循这个说法,也许是我哪里写错了。不过至少map和lamdba可以让程序看起来简洁一些,或者说更酷,更加让人难懂,哈哈。
    改进五:运行时间0:00:00.250000

    import datetime
    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    lines = f.readlines()
    map(lambda x:hashtable.keys().append(x),lines)
    f.close()
    f2.writelines(hashtable.keys())
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)

    这个方法不是我写的,而是qyb文章后一个匿名网友的留言。应该说这个方法我没有想到的主要原因是我确实不知道set类型,-____-#。这个方法无疑是最简洁的一种,虽然效率不如我的第四种改进方式,也许这是因为一些实现上的问题造成的。
    改进六:运行时间0:00:00.219000

    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    f2.write("".join(set(f.readlines())))
    f.close()
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)


    我的结论很简单,Python真的很好用,呵呵。 

    发表于 @ 2006年07月16日 23:40:00|评论(loading...)|编辑

    新一篇: Web应用和PC端软件开发的共同趋势是并行 | 旧一篇: 什么是BOINC?

    评论

    #demo@virushuo 发表于2006-07-18 00:46:00  IP: 67.15.14.*
    TrackBack来自《这个比较的意义在于...》

    昨天给tiny看了一个关于python和c效率的文章。tiny兴致大发,又优化了几个版本,效率有不同程度提高。 其实这个比较,并非在于比较到底python和c那个快。和当初特流行的比较java和c那个快一样,没意义,也无法作到公平的比较。 这事情让我感到震惊的是,python用的是最简单的方式,可以说,学过1天python的程序员就能写的出来。后面的优化也不是什么大不了的算法,都是非常基本的语句换来换去。C就不然了。C的那几段程序,就算是最低效的那个,也不是学1,2个月的c程序员能写出来的。后面的优化版本更是需要不浅的功底。 开发效率,这是核心问题。在这个例子中,初级程序员的初级代码,超过了中级程序员的中级代码。到了高级程序员的话,比较这些基本功已经没意义了,那时侯自然另有一番比法。 脚本语言,早已不是过去所谓的:“开发灵活,简单,但效率较低”能概括的了。不得不承认,脚本语言经过了10年的发展,已经正式登上了这个舞台。 这时候,正如java在企业开发领域推倒C++一样。脚本或称为动态语言成为主流的时刻不远了。...
    #myan 发表于2006-07-17 09:14:00  IP: 219.236.52.*
    精彩 :-)

    tinyfool不妨试试,再你的方案四里,如果用xreadline读文件,速度上是否会有变化?我猜测可能是慢一些。然后再试试:

    # 把这三行
    lines = f.readlines()
    for line in lines:
    hashtable.keys().append(line)

    # 改成
    for line in f:
    hashtable.keys().append(line)

    因为Python 2.2以后,直接在file对象上iteration可能是最快的。我不知道它里面是不是直接用filemapping实现的,但是文档里反正是说它很快。我没有测试样本,你可以再测一测。

    set也是新加进来的,好像是2.3里才有的东西。

    Python确实很好用 :-)
    #tinyfool 发表于2006-07-17 10:44:00  IP: 219.142.220.*
    丢脸了,丢脸了

    为了挽回面子,我和余晟实现了对改进六的改进

    因为输出文件的时候一定会对字符串进行连接,所以join应该是多余的。程序改为:

    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    f2.writelines(set(f))
    f.close()
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)

    刚才测试的结果是改进六 0:00:00.188000
    改进七为 0:00:00.141000

    #ruby 发表于2006-07-17 10:56:00  IP: 210.73.48.*
    #!/usr/bin/env ruby
    t = Time.new

    file = 'email.txt'

    f1= File.new('email.txt', 'r')
    data = f1.readlines
    f1.close

    f2 = File.new('email_new.txt', 'w')
    f2.write(data.uniq.join)
    f2.close

    puts Time.new - t

    0.30... 0.31... 0.29... ....
    #大鱼儿 发表于2006-07-17 11:50:00  IP: 61.135.170.*
    C# 的hashtable居然没有把Keys直接输出成string的方法,所以必须再多做一次操作,速度大大受影响
    #大鱼儿 发表于2006-07-17 11:52:00  IP: 61.135.170.*
    如果去掉最后保存Keys的那段多余代码,C# 和Py在我机器上运行时间相差无几。
    #tinyfool 发表于2006-07-17 09:43:00  IP: 219.142.220.*
    谢谢孟岩。
    xreadline和in f的方案速度几乎一致,都比方案4快些,多次测试下,各有微弱胜负,还是你最厉害啊。

    我办公室机器的测试结果
    方案四 0:00:00.110000
    lines = f.xreadlines() 0:00:00.094000
    for line in f: 0:00:00.094000

    想做测试的朋友可以在http://jason.rocklv.net/techdoc/PythonvsC.html
    一文之后下载测试数据。
    #tinyfool 发表于2006-07-17 11:01:00  IP: 219.142.220.*
    请不要直接贴时间结果,那没有任何意义,大家的机器配置等等完全不同

    请拿第7个改进的py运行结果和你的ruby在同一个机器的运行结果进行比对,否则就不是看程序了,是看机器配置了
    #myan 发表于2006-07-17 09:55:00  IP: 219.236.52.*
    惭愧。其实我是在上次我们三个视频聊天以后,在你们两位的教唆之下才开始正经八北学Python的,功力比你们差远了。只不过恰好以前用过这种方法。

    不过结果真令我震惊啊!
    #tinyfool 发表于2006-07-17 09:58:00  IP: 219.142.220.*
    me too
    #不可比呀 发表于2006-07-17 13:47:00  IP: 211.95.107.*
    光是这样来比,恐怕都是不公平的。

    即使在同一台机器上,各个程序(还不能说是算法)使用
    的内存不一样,所以就没法比。
    #ruby 发表于2006-07-17 13:49:00  IP: 210.73.48.*
    linux/unix下的SHELL
    #cat email.txt | uniq > email_new.txt
    #jawahh 发表于2006-07-17 14:15:00  IP: 57.72.66.*
    cat email.txt | uniq >email_new.txt和上面的算法不一致
    uniq必须用于排序之后的文件,否则不相邻的重复行不会去掉
    #tinyfool 发表于2006-07-17 14:33:00  IP: 219.142.220.*
    sort + uniq就可以了,不过我们在讨论算法和效率优化。。。
    #李卫公 发表于2006-07-17 10:22:00  IP: 61.135.170.*
    程序有问题,哈哈
    import datetime
    if __name__ == "__main__":
    t1=datetime.datetime.today()
    hashtable = {}
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    lines = f.readlines()
    map(lambda x:hashtable.keys().append(x),lines)
    f.close()
    f2.writelines(hashtable.keys())
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)
    这里lambda和map的用法似乎出了问题,因为lambda是有返回值的,而hashtable.keys()只是作为一个参数传进来.....
    我做了测试
    在f.close()前面加上print hashtable
    结果这条语句打印的结果是{}
    #大鱼儿 发表于2006-07-17 17:10:00  IP: 61.135.170.*
    static void Main(string[] args) {
    using (FileStream fs = new FileStream(@"c:\email.txt", FileMode.Open))
    using (FileStream fs1 = new FileStream(@"c:\email.1.txt", FileMode.Create)) {
    Hashtable hs = new Hashtable(0x1000);
    StreamReader sr = new StreamReader(fs, Encoding.ASCII);
    string[] lines = sr.ReadToEnd().Split('\n');
    DateTime start = DateTime.Now;
    StringBuilder sb = new StringBuilder(0x1000);
    foreach(string line in lines) {
    if (!hs.ContainsKey(line)) {
    hs.Add(line, null);
    sb.Append(line);
    sb.Append("\r\n");
    }
    };
    StreamWriter sw = new StreamWriter(fs1, Encoding.ASCII);
    sw.Write(sb.ToString());
    sw.Close();
    DateTime end = DateTime.Now;
    Console.WriteLine(end - start);
    }
    }

    C# 有点烦,写到这里了。 tiny的py在我的机器上跑94ms,C# 的78-95ms
    #tinyfool 发表于2006-07-17 10:26:00  IP: 219.142.220.*
    程序有错误,第四步改进我误解了hashtable.keys(),实际上hashtable.keys()应该是map的键列表的副本,所以对hashtable.keys().append()操作对map本身没有任何影响
    #analyst 发表于2006-07-17 17:18:00  IP: 222.70.121.*
    看来python的字符串内部实现性能确实不错,我用C++写了一个版本,自认为优化的不错了,但也只比改进七快一倍。
    #tinyfool 发表于2006-07-17 10:35:00  IP: 219.142.220.*
    所以第五个改进也有问题。
    #analyst 发表于2006-07-17 17:30:00  IP: 222.70.121.*
    不过像改进七这样的代码已经不关python脚本什么事了,完全是在测试python运行期库的性能,用这样的代码来说明python脚本的性能是会误导大众的。
    #MMII 发表于2006-07-17 16:51:00  IP: 210.82.111.*
    这么多人看好PY,好像PY很牛比似的.
    我们这里C++也用,PY也用,哈哈,如果是PY不用去讨论什么速度,
    除非是你的脑子出了问题!
    明明是东西本身烂,还硬要说他快,说他好.他妈的.
    就像连通天天说自己的信号好一样.
    #matthew 发表于2006-07-17 15:25:00  IP: 202.108.88.*
    追根溯源的精神令人钦佩。

    看运行时间用 time 命令好了,不需要 datetime、Time 这些玩意。我记得 python 有个模块 profile 能帮助做性能分析。
    #cpunion 发表于2006-07-18 00:12:00  IP: 218.1.86.*
    其实老早就做了高效的C++版本。你这个改进6在我的机器上执行时间是1.7秒,改进7在我的机器上1.5-2.6秒不等,反而是第1次最快,郁闷。我的C++版本800多毫秒,蒋黎的版本更快,不过代码量比较多,具体见:
    http://blog.csdn.net/dwbclz/archive/2006/04/06/653294.aspx

    不过不同平台测试结果应该也会有差异,但C++肯定能做出比python快的版本。
    #cpunion 发表于2006-07-18 00:14:00  IP: 218.1.86.*
    忘了说了,我测试的文件是78万行的,是你这个测试文件的10倍。
    #yyp 发表于2006-07-18 02:07:00  IP: 58.49.251.*
    棒 同意作者的看法:我测试了一个200K的文件 每次连续操作10次:
    Test.java
    import java.io.*;
    public class Test {

    public static void main(String[] args){
    java.lang.Runtime run =Runtime.getRuntime();
    java.io.InputStreamReader in;
    java.lang.Process process ;
    java.io.LineNumberReader put;
    try{
    for(int n =0;n<10;n++){
    process =run.exec("/usr/bin/python /home/yyp/work/python/test-"+args[2]+".py");
    in =new InputStreamReader(process.getInputStream());
    put =new LineNumberReader(in);
    String str;
    while((str =put.readLine())!=null){
    System.out.println(str);
    }
    }
    }catch(Exception ex){
    System.out.println(ex);
    }
    }
    }
    ==========测试结果==================
    0:00:00.041188
    0:00:00.038609
    0:00:00.037950
    0:00:00.039114
    0:00:00.039600
    0:00:00.038551
    0:00:00.041109
    0:00:00.038035
    0:00:00.037447
    0:00:00.037714
    ==============================1========================
    0:00:00.023010
    0:00:00.023706
    0:00:00.025185
    0:00:00.025235
    0:00:00.023446
    0:00:00.024477
    0:00:00.024847
    0:00:00.023508
    0:00:00.105961
    0:00:00.024197
    ==============================2========================
    0:00:00.018936
    0:00:00.020977
    0:00:00.020028
    0:00:00.019699
    0:00:00.019719
    0:00:00.020805
    0:00:00.020622
    0:00:00.021651
    0:00:00.019894
    0:00:00.019919
    ========================
    #hoping 发表于2006-07-18 10:05:00  IP: 218.94.83.*
    如果在文件尾确保一个'\n'的话,更加符合Python idiom的写法为:

    import datetime

    if __name__ == "__main__":

    t1=datetime.datetime.today()
    file("email_new.txt", 'w').writelines(set(file("email.txt")))
    t2=datetime.datetime.today()
    print str(t2-t1)
    #hoping 发表于2006-07-18 09:34:00  IP: 218.94.83.*
    程序中没有注意:file的readlines以及readline的返回结果中,最后一行是不带'\n'的,而其他的行带。对于如下情况会导致bug:
    aaa
    bbb
    ccc
    ccc

    最后一行的ccc和前一行ccc读出来是不一样的。
    #hoping 发表于2006-07-18 10:09:00  IP: 218.94.83.*
    如果在文件尾确保一个'\n'的话,更加符合Python idiom的写法为:

    import datetime

    if __name__ == "__main__":

    t1=datetime.datetime.today()
    file("email_new.txt", 'w').writelines(set(file("email.txt")))
    t2=datetime.datetime.today()
    print str(t2-t1)
    #hoping 发表于2006-07-18 09:43:00  IP: 218.94.83.*
    另外,直接写成这种形式:

    for line in file("email.txt","r"):
    hashtable.keys().append(line)

    不仅更简洁,而且Python会保证close file的,不用自己close了。
    #OOB 发表于2006-07-18 09:05:00  IP: 210.82.111.*
    这时候,正如java在企业开发领域推倒C++一样。脚本或称为动态语言成为主流的时刻不远了。...

    不敢苟同!
    JAVA能在企业级开发站住脚靠的是它本身是个平台,而不是靠语言本身, 你做WEB开发,JAVA有一套构架,卡发服务端应用,JAVA还有一套标准,你只要在适当的地方写上你的代码就行了,只是其他的由平台或应用服务器替你做了.这才是它开发快的原因. 而且这种开发限制也比较大,只适合哪些执行速度要求不高,但安全性稳定性高的环境.

    不过PYTHON就看不到这些了,它不是个开发平台,只是个教本语言,如果没有平台的概念在里面,没有什么意义的. 和PERL没有什么区别,就象PERL一样,开始说的挺火,现在没落了.谁还去用它呢.

    网路上很多人在抄PY,我看是头脑出问题了.有些鄙视这些人.

    C++ 不会过时,说它过时的人,是你自己被淘汰了.你不会用C++,那只能说明你能力有限,水平低!
    真正的程序员用C++!

    #king 发表于2006-07-18 14:37:00  IP: 218.64.21.*
    不知道用c++的std::map怎么样?谁测试一下啊。
    #csdn blog 编辑 发表于2006-07-18 14:12:00  IP: 218.247.0.*
    Tinyfool网友,经过CSDN Blog专家顾问团的合议,您的文章:"一个Python程序的6次改进",成为7月15-16日的“每日一帖”!请参考下面的提示和我们联系领取奖品事宜,谢谢你向广大CSDN网友分享你的原创文章。

    提示:
    1.评选时间为周一至周五!
    2.请您及时查看和关注您的个人Blog,我们会以评论的形式告诉您获奖的信息。
    3.本次活动奖品是由第二书店提供的100个D币,请访问第二书店(www.dearbook.com.cn)激活您的D币帐号;激活后请将您[Dearbook的注册邮件]/[Blog的帐号]//[获奖文章名称]/[获奖日期]回复邮件给我们的编辑gaocao(AT)csdn.net;
    4.请各位网友及时查收您的D币帐号,有问题及时和我们联系,或者在本栏目评论。
    5.[每日一帖]不断更新中…… 明天将评选出今天的每日一帖
    6.详细请参考:http://blog.csdn.net/todaypost/
    #Jan 发表于2006-07-18 23:46:00  IP: 219.82.143.*
    不容易啊... 有没有人写个stl的版本
    #analyst 发表于2006-07-18 21:52:00  IP: 222.70.127.*
    经过我多次实验和改进以后,终于实现出了这个比Python版快三倍的C++版本。

    #include <windows.h>
    #include <mmsystem.h>
    #include <fstream>
    using namespace std;
    #pragma comment(lib, "winmm.lib")

    int GetHash(char* key, int len)
    {
      int hash = 0;
      while(len-- > 0)
        hash = (hash * 11) + *key++;
      return hash;
    }

    struct Node
    {
      char* str;
      int len;

      Node()
      {
      }

      Node(char* _str, int _len)
        : str(_str), len(_len)
      {
      }
      bool operator == (const Node& node)
      {
        if(len != node.len)
          return false;
        for(int i = 0; i < len; ++i)
          if(str[i] != node.str[i])
            return false;
        return true;
      }
    };


    class OfstreamBuffer
    {
      ofstream& ofs;
      size_t buf_size;
      size_t offset;
      char* buffer;

    public:
      OfstreamBuffer (ofstream& ofs_, size_t buf_size_)
        : ofs(ofs_), buf_size(buf_size_), offset(0)
      {
        buffer = new char[buf_size_];
      }

      ~OfstreamBuffer ()
      {
        flush();
        delete[] buffer;
      }

      void write (const char* ptr, size_t size)
      {
        while (size > 0)
        {
          size_t copy_size = buf_size - offset;
          if (copy_size > size)
            copy_size = size;
          memcpy (buffer + offset, ptr, copy_size);
          offset += copy_size;
          ptr +=
    #shshsh_0510 发表于2006-07-19 10:09:00  IP: 172.23.9.*
    结论正确:Python真的很好用。
    但是论述内容和结论基本上无关:)

    如果是想通过改善了Python效率,进而推翻qyb的结论,从而得出“Python不仅比C好用,而且比C快“的结论,那就是错误的了。

    用上面引文,以及引文的引文的方法比较两种语言,是完全不着边的方法,那是在比较两个hash库的实现效率。
    #tinyfool 发表于2006-07-19 10:42:00  IP: 219.142.220.*
    python真的好用是我的感受,请注意,我没有任何一句话包含对python和c的运行效率的结论。我只是说那个python程序可以优化而已,请仔细看看我的标题和我的所有内容。

    我可没那么无聊,楼上诸位,我不多说啥了。
    #韩磊 发表于2006-07-19 12:02:00  IP: 61.49.227.*
    文章不错,讨论更好。
    #dennis 发表于2006-07-19 12:57:00  IP: 58.23.92.*
    受益非浅
    #myan 发表于2006-07-19 23:11:00  IP: 58.33.187.*
    to anyalst:
    在GetHash里把11换成37,效率是否能进一步提高?
    #shshsh_0510 发表于2006-07-20 09:21:00  IP: 172.23.9.*
    结论是容易得出的:在没有算法本质的改进的前提下,利用通用的hash库算法以及语言流行类库所提供的通用的IO优化机制,在数据量较大的情况下,两种语言对于这一简单问题的结果,速度差应该不超过1倍!

    如果针对mail地址字符串规律,定制算法,那么还是有可能在数量级上的提高的。要做这种事的话,我本人会选择C的

    楼主很细致的优化说明了楼主的趣向及思维方式,但我们也可以从qyb不效率的程序看到另一种思维:抓住主要,不顾小节。
    要知道,我们学会有个readline能实现某个功能已经不容易了,如果还要求我们再知道readlines,并且还要知道readline与readlines的区别,进而还要知道readliness ,.readlinesss.....

    其实,我们只需要知道在必要的时候,注意优化一下IO就可以了,这个例子应该属于不必要的那类 :)
    #alin 发表于2006-07-20 13:07:00  IP: 60.176.206.*
    方法7,


    我把那个email文件搞到1000w行180m 1%重复,结果搞到内存170m多,38s执行完
    #perryhg 发表于2006-07-20 19:26:00  IP: 58.39.2.*
    ...我把那个email文件搞到1000w行180m...

    这种优化都不过是仗着内存多而已,给你给1亿行的文件就没那么好用了
    #hhhm 发表于2006-07-21 14:08:00  IP: 210.82.111.*
    python真的好用是我的感受,请注意,我没有任何一句话包含对python和c的运行效率的结论。我只是说那个python程序可以优化而已,请仔细看看我的标题和我的所有内容

    python真的好用吗!!!那不过是你自己的感觉而已!我现在C++和PYTHON都在用,不过PY刚开始用,觉得很难使用,一堆一堆的问题,相比之下C++倒是好多了.同样的功能我用C++开发和PY教本程序员没什么时间差,看你自己的熟练程度了.
    看你写的东西,动不动就说到为什么选PYTHON,就是开发效率效率效率. 操,什么东西用熟练了都会快,不熟悉就不会快. 前面有个老大说了都,PYTHON不是个平台,我同意,一个小小的脚本语言,搞不懂你们整天都去想整出个什么特性出来,和这个比和那个语言比!!等PYTHON被世人渐渐忘记的时候,你就该清醒了.!!!!!!

    #Ishou 发表于2006-07-22 22:39:00  IP: 202.156.157.*
    大概 hhhm 没有把 Python用在点子上吧,呵呵!您如此瞧不起“小小的脚本语言”,又如何发现其开发效率的优势所在?脚本语言的一个优势就在于其“小小”特征!


    #hhhm 发表于2006-07-23 11:15:00  IP: 210.82.111.*
    :大概 hhhm 没有把 Python用在点子上吧,呵呵!您如此瞧不起
    :“小小的脚本语言”,又如何发现其开发效率的优势所在?脚本语
    :言的一个优势就在于其“小小”特征!

    只有时间才能证明一切!
    等PYTHON被世人渐渐忘记的时候,你就该清醒了.!!!!!!

    #Ishou 发表于2006-07-23 14:24:00  IP: 202.156.157.*
    也许Python等许多动态型语言在将来会被更好的同类语言所取代,但是不能因此而否定这些语言在今日的地位和作用,谁可以完全确定现在使用的任何语言,包括C/C++在内 绝对不会在将来被更好的语言取代, 难道我们现在就应该干脆 不要重视这些语言?

    PYTHON不是一个完美、理想的脚本语言, 但是在许多方面还是挺实用的, 毕竟迄今还没有出现让众人满意的脚本语言。

    在本质上,脚本语言是C/C++的延续, 把日常C/C++编程中大量 重复、烦琐的程序部分进行重新整理、规范等,打包(编译)成“脚本语言”,通过脚本语言方式间接调用这些 C/C++程序。脚本语言“解释”过程会消耗时间,但是,所执行(调用)的C/C++程序的运行可能也相当耗费时间,甚至使得 脚本语言的“解释”消耗的时间相对来说,变得微不足道,那么,此时脚本语言与 纯粹的C/C++程序语言的运行效率就没有多大差别了。 脚本语言的运行效率一般贵在简短的程序码!

    #LINUXHEART 发表于2006-07-24 08:38:00  IP: 211.100.30.*
    .

    #林中雨 发表于2006-07-24 10:20:00  IP: 220.232.106.*
    C和C++都有HASH库. 能实现一个好的HASH算法.那是高人呀,呵呵.用人家的库那时多么的简单.不值得吹嘘.
    #shhgs 发表于2006-07-25 07:10:00  IP: 70.27.117.*
    性能这东西就是一条线,达线之后再比较快多少倍就没意义了。

    0.01秒和0.0001秒对用户来说都是一样的,但是其性能差距是100倍。

    Py的优势是开发速度。那个比Py快3倍的C++的程序,要写多长时间?30倍都不止吧。况且对大多数人来说,随手一写的C++程序,很有可能并不比Py的快很多。

    此外,就这个问题,我有一点疑问。你们整理完email.txt之后不需要保留行的先后顺序吗?

    lines = file('email.txt').readlines()
    output = []
    try :
    while 1 :
    line = lines.pop()
    if line not in output : output.append(line)
    except :
    file('output', 'w').writelines(output)
    #formain14 发表于2006-07-25 10:18:00  IP: 61.135.152.*
    这里C++的鼓吹者看来都比较激动,估计都是windows程序员吧。

    linux下比较少见只会C++不会C的,而如果会C的话,就不会用C++来做算法。:)
    #tinyfool 发表于2006-07-25 10:07:00  IP: 219.142.220.*
    在这个问题里面,先后顺序没关系
    #glava 发表于2006-07-25 10:49:00  IP: 210.22.177.*
    有意思,我也贴个ruby版的,除去benchmark,还少一行,呵呵
    require 'benchmark'

    puts Benchmark.realtime() {||
    filename = "c:/email.txt"
    oFile = File.new("c:/email_ruby.txt","w")
    emailList = {}
    IO.readlines(filename).each do |line|
    if(emailList[line] == nil)
    emailList[line] = true
    oFile.puts line
    end
    end
    }
    #analyst 发表于2006-07-25 15:50:00  IP: 222.70.130.*
    用C++的意义就在于,当python写到极限file("email_new.txt", 'w').writelines(set(file("email.txt")))后无法再深入下去的时候,C++还可以不断的挑战算法的极限,榨干系统的所有潜能,针对不同的情况选择不同的策略,2倍3倍甚至更多的把性能提高下去,对C++程序员来说优化是没有极限的。尽管这只是一个纯粹的性能优化游戏,但是用python如何体会的到C++在优化中所获得的乐趣呢?
    从实用主义角度讲,仅仅安于完成任务的程序员只能成为平庸的程序员,而那些能够把性能发挥到极至的程序员(像John Carmark之类)才是真正卓越的程序员。
    #niyue 发表于2006-07-25 22:10:00  IP: 218.1.127.*
    有点意思,学习py中
    #softly 发表于2006-07-26 10:38:00  IP: 58.212.223.*
    牛人啊!

    羡摹
    #faku 发表于2006-07-26 17:24:00  IP: 218.80.193.*
    一帮人渣
    #faku 发表于2006-07-26 17:25:00  IP: 218.80.193.*
    中国就是因为有你们这帮人才。。。
    #tbyxyz 发表于2006-07-26 21:34:00  IP: 124.193.12.*
    // TestTime.cpp : 定义控制台应用程序的入口点。
    //

    #include "stdafx.h"
    #include <stdio.h>
    #include <windows.h>
    class CStopwatch {
    private:
    LARGE_INTEGER m_liPerfFreq;
    LARGE_INTEGER m_liPerfStart;
    public:
    CStopwatch() {
    QueryPerformanceFrequency(&m_liPerfFreq);
    Start();
    }
    void Start() {
    QueryPerformanceCounter(&m_liPerfStart);
    }
    double Now() const {
    LARGE_INTEGER liPerfNow;
    QueryPerformanceCounter(&liPerfNow);
    return (
    (liPerfNow.QuadPart - m_liPerfStart.QuadPart)
    / (double)m_liPerfFreq.QuadPart);
    }
    };

    #include <atlcoll.h>
    #include <string>
    using namespace std;

    template<>
    class CDefaultHashTraits<string>
    {
    public:
    static ULONG Hash( const string& s ) throw()
    {
    unsigned long __h = 0;
    int len = s.length();
    for (int i= 0 ; i < len; ++i)
    __h = 5*__h + s[i];
    return size_t(__h);
    }
    };

    int _tmain(int argc, _TCHAR* argv[])
    {
    CAtlMap<string, int> atlMap;
    CStopwatch watch;

    FILE* f = fopen("e:\\email.txt", "r");
    fseek(f, 0, SEEK_END);
    int textLen = ftell(f);
    char buf[100];
    char* text = new char[textLen];
    fseek(f, 0, SEEK_SET);
    char* begin = text;
    while (fgets(buf, 100, f) != NULL)
    {
    if (!atlMap.Lookup(buf))
    {
    str
    #tbyxyz 发表于2006-07-26 21:56:00  IP: 124.193.12.*
    CE1.4G 512M

    0.228155s


    // TestTime.cpp : 定义控制台应用程序的入口点。
    //

    #include "stdafx.h"
    #include <stdio.h>
    #include <windows.h>
    class CStopwatch {
    private:
    LARGE_INTEGER m_liPerfFreq;
    LARGE_INTEGER m_liPerfStart;
    public:
    CStopwatch() {
    QueryPerformanceFrequency(&m_liPerfFreq);
    Start();
    }
    void Start() {
    QueryPerformanceCounter(&m_liPerfStart);
    }
    double Now() const {
    LARGE_INTEGER liPerfNow;
    QueryPerformanceCounter(&liPerfNow);
    return (
    (liPerfNow.QuadPart - m_liPerfStart.QuadPart)
    / (double)m_liPerfFreq.QuadPart);
    }
    };

    #include <atlcoll.h>
    #include <string>
    using namespace std;

    template<>
    class CDefaultHashTraits<string>
    {
    public:
    static ULONG Hash( const string& str ) throw()
    {
    unsigned int hash = 5381;

    for(unsigned int i = 0; i < str.length(); i++)
    {
    hash = ((hash << 5) + hash) + str[i];
    }

    return (hash & 0x7FFFFFFF);

    }



    };

    unsigned int ELFHash(const std::string& str)
    {
    unsigned int hash = 0;
    unsigned int x = 0;

    for(unsigned int i = 0; i < str.length(); i++)
    {
    hash = (hash << 4) + str[i];
    if((x = hash & 0xF0000000L) != 0)
    {
    hash ^= (x >> 24);
    hash
    #shhgs 发表于2006-07-27 08:22:00  IP: 70.27.117.*
    to glava

    比较代码的行数是没有意义的。

    这里,如果要写得简洁,一行就够了
    file('output', 'w').write(''.join(set(file('input').readlines())))

    当然,可读性比较差,比较值得推荐的写法是
    lines = file('input').readline()
    text = ''.join(set(lines))
    file('output', 'w').write(text)

    倒是直接耍filename的作法不值得推荐。这里用stdin/stdout比较好。
    #shhgs 发表于2006-07-27 08:40:00  IP: 70.27.117.*
    TO analyst

    不赞成你对优化的看法。

    优化体现在数据结构和算法的设计上。这里,不论是C++还是Python的实现,从数据结构和算法角度看,完全是相同的。因此它们之间的性能差异,根本不值得程序员去花很大的力气去争取。

    真正的优化是要把算法的复杂度降低。要让这个解决方案能复制到其它地方。就好像快速排序法对冒泡法的优化那样。

    #analyst 发表于2006-07-27 11:48:00  IP: 58.38.85.*
    那我只能说你对优化的认识还远远不够。
    优化并不仅仅局限于算法级,即使同样复杂度的算法在不同的实现下,性能差上1、2个数量级都是很正常的。不深入了解计算机体系结构,不熟悉系统的底层,是做不好优化的。
    John Carmark并没有发明过什么新算法,但是他使得原本那些实验室里的图形算法性能提高了1个数量级,几乎做到了最优实现才使其可以实时的在普通PC上运行。
    #Copper 发表于2006-07-27 12:45:00  IP:
    知其然不知起所以然,也敢在这里比较算法优劣
    国人果然堕落了,连这种文章都称赞
    我也堕落了,居然来看这种文章
    唉。。。
    不懂就别出来评测
    #zhaozg 我来一个LUA的 发表于2006-10-04 06:52:00  IP: 221.219.156.*
    lines = {}

    f1 = io.open ("email.txt","r")
    for line in f1:lines() do lines[line] = true end
    f1:close()

    f2 = io.open ("e_t.txt","w+")
    for line in pairs(lines) do f2:write(line, "\n") end
    f2:close()
    print(os.clock())

    tinyfool的最快的那个在我机器跑 为 0.171 python2.5
    我的lua的脚本要 0.509 lua 5.1
    测试数据从 http://jason.rocklv.net/downloads/email2.txt 下载
    三倍的性能,python的表现让我吃惊,用空写个加速版本给大家看看!
    #zhaozg 发表于2006-10-04 22:09:00  IP: 61.49.109.*
    下面是总结出来的最快的python实现
    import datetime

    if __name__ == "__main__":
    t1=datetime.datetime.today()
    f = file("email.txt","r")
    f2 = file("email_new.txt","w")
    f2.writelines(set(f))
    f.close()
    f2.close()
    t2=datetime.datetime.today()
    print str(t2-t1)

    在我机器上的测试结果:
    python 2.5: 0:00:00.172000
    这个程序语言特性用到了极致, 近乎完美地解决了问题,佩服!

    一位网友的ruby实现
    #!/usr/bin/env ruby
    t = Time.new

    file = 'email.txt'

    f1= File.new('email.txt', 'r')
    data = f1.readlines
    f1.close

    f2 = File.new('email_rb.txt', 'w')
    f2.write(data.uniq.join)
    f2.close
    puts Time.new - t

    ruby 2.0.0 (Base: Ruby 1.9.0 2006-04-08) [i386-mswin32]
    YARVCore 0.4.1 Rev: 545 (2006-09-01) [opts: [inline method cache] ]

    这个程序也很酷,语言特新叶很到位, 结果 0.391

    看了之后,马上产生了用lua写一个同样程序的想法!

    lines = {}

    f1 = io.open ("email.txt","r")
    for line in f1:lines() do lines[line] = true end
    f1:close()

    f2 = io.open ("e_t.txt","w+")
    for line in pairs(lines) do f2:write(line, "\n") end
    f2:close()
    print(os.clock())

    Lua 5.1.1 Copyright (C) 1994-2006 Lua.org, PUC-Rio: 0.406
    测试结果: Python:Ruby:Lua = 172:391:406

    python是从官网下的Win32安装版, Ruby,LUA都是静态编译static的版本!从这一点上说,如果python静态编译的话,应该还可以更快!

    是不是LUA就差了呢!lin
    #RockmanZero 发表于2007-12-06 09:04:16  IP: 10.197.21.*
    还是那句话,
    楼主长得真猥琐.
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © Tinyfool