Hello World
Spiga

尝试使用IKVM运行Lucene 2.9.0版

2009-10-09 15:26 by 老赵, 13261 visits

上月末Lucene发布了2.9.0版,这个版本的改进比较明显,主要是各方面性能的增强,以及对数字字段范围查询的直接支持。这个版本还有个重要的意义,就是它标记了Lucene 3在API上的改变,及早跟进的话对Lucene 3的未来接受程度会比较好。Lucene的更新很慢,而移植到.NET平台上的Lucene.NET二进制发布则更是一直停留在07年三月的2.0版本。虽然我们可以通过svn获取到Lucene.Net 2.3.2的源代码自行编译,但这次我还是想直接使用最新的2.9.0版本。

至于如何在.NET平台上调用Java代码,我想过各种方式,例如我最初设想使用Java => JNI => C++/CLI => C#的“曲线救国”方式,也考虑过最保险的借助HTTP做Proxy的方式。不过最后在RednaxelaFX的建议下,我决定趁这个机会尝试一下IKVM.NET(下文称为IKVM)。IKVM的目的是在.NET平台(包括mono)上实现一个Java执行环境(也就是JVM),它可以将jar包直接运行在.NET平台上,将Java语言的源文件编译为.NET的程序集,而现在我们使用它的另一个功能,直接把Lucene 2.9.0的二进制jar包转化为.NET下的dll。

IKVM在我博客的侧边栏上停留了很久,不过我一直认为它还不太成熟于是没有怎么去接触。现在从Case Studies上来看,IKVM的可用性似乎还是有一定保障的。IKVM目前实现了JDK 1.6,也可谓紧跟Java脚步。对于这种转化,首先要看中的应该是“正确性”,对于纯粹内存中的对象来说,我猜想应该不会有什么正确性方面的问题。而IO操作就相对值得斟酌了,例如对于文件锁的处理,对于数据流的读写,即使差1个字节可能也会造成大问题。不过,就我初步使用下来的感受,效果比想象中要好很多。在我测试的场景下,使用IKVM Lucene和Java Lucene的索引可以互相读写,没有发生任何问题。当然,这还需要更进一步的测试,这也是我写这篇文章的目的。

在保证了正确性之后,要关注的便是性能了。根据我的推测,由于IKVM需要在Java生成的.NET程序集和BCL之间加上一层Runtime和JDK,因此其性能几乎一定会比Java原有的程序要差。不过,对于Lucene这种项目来说,算法才是性能的关键。例如,有人测试Lucene 2.9.0在某些情况下会比2.4有15倍左右的性能提升。不过由于没有很好的测试数据和场景,目前我只进行了最最简单的,不涉及磁盘IO的性能比较。

性能比较的场景很简单,我准备了《神雕侠侣》全文作为索引数据,2兆多的文本文件,反复使用StandardAnalyzer向RAMDirectory中添加索引,并在以下四种环境下统计索引100遍所消耗的时间(统计时都会对JIT进行“预热”)。

  • 在.NET平台下使用Lucene.Net 2.3.2(需获取源代码自行编译)。
  • 在.NET平台下使用IKVM运行Lucene 2.9.0。
  • 在Java平台下使用默认的Client VM运行Lucene 2.9.0。
  • 在Java平台下使用Server VM(加-server参数)运行Lucene 2.9.0。

我将所有的测试数据、类库、源文件都打包了,感兴趣的朋友可以下载以后查看。压缩包内的DotNet和Java目录中有着相似的内容:

  • lib目录:保存所需的类库(dll或jar文件)
  • src目录:保存测试用源代码(cs或java文件)
  • build.bat:调用csc或javac编译src下的源文件,将结果输出至bin目录
  • clean.bat:清除编译结果(即删除build文件)
  • run.bat:运行测试程序

在执行build.bat文件的时候,需要保证PATH中包含了正确的目录,可以访问到csc或者javac。在使用run.bat运行测试程序时,也可以添加参数进入不同的分支。例如对.NET的测试中:

...\DotNet> build

...
...

...\DotNet> :: 测试Lucene.Net 2.3.2
...\DotNet> run

...
...

...\DotNet> :: 测试IKVM Lucene 2.9.0
...\DotNet> run -ikvm

...

而在Java的测试中:

...\Java> build

...
...

...\Java> :: Client VM
...\Java> run

...
...

...\Java> :: Server VM
...\Java> run -server

...

在我的笔记本上(Windows 7,双核2.0 Ghz CPU,2G RAM),执行结果如下:

以上图表展示的是每种环境下各执行3次的平均耗时。可见,性能从高到低依次如下:

  1. Java Server VM + Lucene 2.9.0
  2. .NET + Lucene.Net 2.3.2
  3. Java Client VM + Lucene 2.9.0
  4. .NET + IKVM + Lucene 2.9.0

从结果上看,Java Server VM的表现最好,而且领先幅度较大,相对于IKVM有35%左右的性能优势。不过这个结果让我非常满意,因为在我看来,这完全处在一个可以接受的范围之内,绝大部分系统根本不会在乎这点性能差距。Java平台的优势是类库数量,如果IKVM可以仅靠这点性能损失换来.NET对Java类库的使用能力,天下没有更合算的事情了。

不过让我更加感兴趣的是Java Server VM + Lucene 2.9.0和.NET + Lucene .Net 2.3.2的比较结果,我承认这个差距让我始料未及,因为就我过去的经验,相同的.NET和Java应用程序,.NET的性能会领先Java。在简单思考过后,我猜想有以下的几点可能:

  • Lucene 2.9.0的算法本身比Lucene 2.3.2效率高。
  • JVM的Memory Consistency Model比CLR来的宽松,因而高效。
  • JVM的JIT优化比CLR做的好。

HotSpot的白皮书称,Server VM与Client VM的除了Heap大小,GC等参数方面不同以外,最大的区别在于Server的JIT会尝试更多的优化手段,这会导致较多的启动时间,以此换来更好的执行效率:

The Client VM compiler does not try to execute many of the more complex optimizations performed by the compiler in the Server VM, but in exchange, it requires less time to analyze and compile a piece of code. This means the Client VM can start up faster and requires a smaller memory footprint.

The Server VM contains an advanced adaptive compiler that supports many of the same types of optimizations performed by optimizing C++ compilers, as well as some optimizations that cannot be done by traditional compilers, such as aggressive inlining across virtual method invocations. This is a competitive and performance advantage over static compilers. Adaptive optimization technology is very flexible in its approach, and typically outperforms even advanced static analysis and compilation techniques.

而编译器及虚拟机大牛RednaxelaFX在推特上也告诉我:

话说GC方面CLR或许非常先进,但JIT方面就还是HotSpot强(和复杂)一些了。CLR没办法inline虚方法或者接口上的方法的调用,HotSpot却可以……总之这种对比的结果要看你测试的代码的性质

至于具体的情况,RednaxelaFX建议查看HotSpot和CLR在JIT之后的Native Code,这并非我所擅长的东西,于是就希望R大可以给出更详细的结果了。:)

最后,便是本文的目的了:目前的测试缺少实际价值,那么您有兴趣和我一起做一个更接近生产环境的实验吗?或者说,您在生产环境中是如何使用Lucene的呢?

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

31 条回复

  1. zffl
    *.*.*.*
    链接

    zffl 2009-10-09 15:37:00

    学习了,我也要试试

  2. 呵呵呵呵呵呵呵[未注册用户]
    *.*.*.*
    链接

    呵呵呵呵呵呵呵[未注册用户] 2009-10-09 15:38:00

  3. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-10-09 15:59:00

    吐槽来了
    也可谓紧跟Java脚本 =〉也可谓紧跟Java脚步

  4. 采飞扬
    *.*.*.*
    链接

    采飞扬 2009-10-09 16:05:00

    比较关心测试数据是怎么得出来D,呵呵

  5. 老赵
    admin
    链接

    老赵 2009-10-09 16:06:00

    @采飞扬
    不都给出测试代码,测试数据,编译脚本,运行脚本了吗?

  6. 老赵
    admin
    链接

    老赵 2009-10-09 16:06:00

    @韦恩卑鄙
    oyeah

  7. 田忌赛马?[未注册用户]
    *.*.*.*
    链接

    田忌赛马?[未注册用户] 2009-10-09 16:14:00

    “不过让我更加感兴趣的是Java Server VM + Lucene 2.9.0和.NET + Lucene .Net 2.3.2的比较差距,我承认这个差距让我始料未及,因为就我过去的经验,相同的.NET和Java应用程序,.NET的性能会领先Java。”

    怎么不是用同一版本的Lucene来进行比较呢?如果问错请包涵,我不了解Lucene各版本之间的性能差别,但是如果有这种可能性的话“有人测试Lucene 2.9.0在某些情况下会比2.4有15倍左右的性能提升”...

  8. 采飞扬
    *.*.*.*
    链接

    采飞扬 2009-10-09 16:15:00

    @Jeffrey Zhao
    这么说运行一下数据就出来了吧,偶试下
    谢谢

  9. 老赵
    admin
    链接

    老赵 2009-10-09 16:32:00

    @田忌赛马?
    因为Lucene.Net没有更新的版本,我不想挖Java的旧版出来了。
    文章后面也提到了“Lucene 2.9.0的算法本身比Lucene 2.3.2效率高”的可能,不过这不是比较的关键。

  10. 菜鸟2009[未注册用户]
    *.*.*.*
    链接

    菜鸟2009[未注册用户] 2009-10-09 16:32:00

    我们用的是solr做服务器,采用http方式通讯来执行搜索。

  11. 老赵
    admin
    链接

    老赵 2009-10-09 16:33:00

    @采飞扬
    以后还是仔细看看文章吧,我写一遍已经不容易了,体谅体谅,呵呵。

  12. 老赵
    admin
    链接

    老赵 2009-10-09 16:48:00

    @菜鸟2009
    http是各平台结合的好东西。

  13. 菜鸟2009[未注册用户]
    *.*.*.*
    链接

    菜鸟2009[未注册用户] 2009-10-09 16:51:00

    老赵你们为什么不用solr?

  14. 老赵
    admin
    链接

    老赵 2009-10-09 16:54:00

    @菜鸟2009
    因为solr也就是对lucene的再封装而已,我喜欢直接使用,当然现在的试验目的更多一些。

  15. sig556
    *.*.*.*
    链接

    sig556 2009-10-09 17:16:00

    试试

  16. 采飞扬
    *.*.*.*
    链接

    采飞扬 2009-10-09 17:53:00

    @Jeffrey Zhao
    只喜欢看图,哈哈
    再次感谢

  17. 采飞扬
    *.*.*.*
    链接

    采飞扬 2009-10-09 18:00:00

    java:
    10 2750
    20 5484
    30 8234
    40 11062
    50 13906
    60 16672
    70 19437
    80 22203
    90 24969
    100 27703
    .net暂时没环境

  18. 老赵
    admin
    链接

    老赵 2009-10-09 18:37:00

    @采飞扬
    client?server?
    // 你的机器没我好,嘿嘿。

  19. GWPBrian
    *.*.*.*
    链接

    GWPBrian 2009-10-09 19:27:00

    不错

  20. 老赵
    admin
    链接

    老赵 2009-10-09 20:34:00

    话说我打算把博客园的所有文章索引一下作为测试数据,就从下面的链接入手了
    http://www.cnblogs.com/AllBloggers.aspx

  21. Lion
    *.*.*.*
    链接

    Lion 2009-10-10 09:02:00

    不错 为大家提供了更多的思路

  22. 菜鸟2009[未注册用户]
    *.*.*.*
    链接

    菜鸟2009[未注册用户] 2009-10-10 10:44:00

    Jeffrey Zhao:
    @菜鸟2009
    因为solr也就是对lucene的再封装而已,我喜欢直接使用,当然现在的试验目的更多一些。



    我们老板认为是重复发明轮子的问题。

  23. 老赵
    admin
    链接

    老赵 2009-10-10 11:27:00

    @菜鸟2009
    你以为我在用lucene,我觉得我在用ikvm。这就是我和你老板的视角不同。
    还有就是,在很多场景下当然是直接用lucene比用solr来得简单、稳定。

  24. JimLiu
    *.*.*.*
    链接

    JimLiu 2009-10-11 11:00:00

    IKVM...
    JAVA.NET,.NET又能跑MONO,真飘逸。
    不过看来执行效率还是比较一般。

  25. 老赵
    admin
    链接

    老赵 2009-10-11 11:02:00

    @JimLiu
    平白无故多了一层,自然性能会降低。但是这点降低真没啥关系,否则ruby等脚本语言与.net相比几倍几倍的性能差距,还要不要活了,呵呵。

  26. JimLiu
    *.*.*.*
    链接

    JimLiu 2009-10-11 13:25:00

    @Jeffrey Zhao
    嗯,“性能”其实是个很模糊的词。
    我只是觉得这个世界太奇妙了,都说.NET平台独占,现在不仅MONO开始发展壮大了,弄的JAVA还能跑在CLR上。山不转水转,真是有趣。

  27. longware0[未注册用户]
    *.*.*.*
    链接

    longware0[未注册用户] 2009-11-02 14:39:00

    C:\temp\Java>java 。。。。。
    Finished 750
    Press enter to start...

    10 1844
    20 3688
    30 5532
    40 7469
    50 9282
    60 11110
    70 12985
    80 14891
    90 16797
    100 18672
    Finished 18672
    press enter to exit...

    --------------------

    C:\temp\DotNet>bin\IndexBenchmark.exe "..\Data"
    Finished 349
    Press enter to start...

    10 1747
    20 3565
    30 5325
    40 7063
    50 8811
    60 10562
    70 12331
    80 14107
    90 15849
    100 17569
    Finished 17569
    press enter to exit...

  28. withtao[未注册用户]
    *.*.*.*
    链接

    withtao[未注册用户] 2009-12-23 14:43:00

    你好,能把你编译好的dll发我一个吗?我编了半天还是失败了 谢谢了

  29. withtao[未注册用户]
    *.*.*.*
    链接

    withtao[未注册用户] 2009-12-23 14:55:00

    @withtao
    没看到 下载链接 不好意思

  30. withtao[未注册用户]
    *.*.*.*
    链接

    withtao[未注册用户] 2009-12-23 14:57:00

    楼主能尝试下编译 bobo_browse吗?我没编译成功

  31. hzsong123
    221.219.197.*
    链接

    hzsong123 2014-12-15 23:01:34

    老赵,我最近准备将若干个Java项目转化为C#项目(源码级转化),我选择了Sharpen+IKVM.net,但是IKVM不支持泛型,很是令人头疼,你有什么好的建议吗? 如果只依靠IKVM.net,只能得到dll,并不能得到源码(反编译没有源码注释信息),我也是很恼火。 另外Ja.net: http://sourceforge.net/projects/janetdev/,你用过吗?这个也是挺好的。 谢谢你的帮助。黄志松,hzsong123@126.com

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我