隨筆 - 3  文章 - 10  trackbacks - 0
          <2012年12月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          常用鏈接

          留言簿(3)

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          jni的幾個基本的性能測試分析

          今天對jvm運(yùn)行jni做了幾個基本的性能測試,測試的jvm有jdk1.4.2_19、jdk1.5.0_04和jdk1.6.0_14,測試的重復(fù)次數(shù)都是一億次,測試結(jié)果的絕對數(shù)值意義不大,僅供參考。
          java調(diào)用jni空函數(shù)和調(diào)用java方法的性能(比較):
          java.version = 1.6.0_14
           Java空方法調(diào)用  耗時 329 ms   平均每秒  303951367
           JNI空方法調(diào)用   耗時 1531 ms  平均每秒  65316786

          java.version = 1.5.0_04
           java空方法調(diào)用  耗時 312 ms   平均每秒  320512820
           JNI空方法調(diào)用   耗時 1891 ms  平均每秒  52882072

          java.version = 1.4.2_19
           java空方法調(diào)用  耗時 312 ms   平均每秒  320512820
           JNI空方法調(diào)用   耗時 3672 ms  平均每秒  27233115
           
           jdk版本越高,JNI調(diào)用的性能越好,這點(diǎn)要感謝sun的努力了。
          在jdk1.6下,僅僅是空方法調(diào)用,JNI的性能就要比java內(nèi)部調(diào)用慢將近5倍,而在jdk1.4下更是慢了十多倍。

           

          jni里查找class(JNIEnv.FindClass)和fieldid(JNIEnv.GetFieldID)和jni讀取java Field(JNIEnv.GetFieldValue)的性能:
          緩存表示只調(diào)用一次,不緩存就是每次都調(diào)用。

          java.version = 1.6.0_14
          JNI 字段讀取 (緩存Class=false ,緩存字段ID=false) 耗時 : 79172 ms    平均每秒 : 1263072
          JNI 字段讀取 (緩存Class=true ,緩存字段ID=false)  耗時 : 25015 ms    平均每秒 : 3997601
          JNI 字段讀取 (緩存Class=false ,緩存字段ID=true)  耗時 : 50765 ms    平均每秒 : 1969861
          JNI 字段讀取 (緩存Class=true ,緩存字段ID=true)   耗時 : 2125 ms     平均每秒 : 47058823

          java.version = 1.5.0_04
          JNI 字段讀取 (緩存Class=false ,緩存字段ID=false) 耗時 : 87109 ms    平均每秒 : 1147987
          JNI 字段讀取 (緩存Class=true ,緩存字段ID=false)  耗時 : 32031 ms    平均每秒 : 3121975
          JNI 字段讀取 (緩存Class=false ,緩存字段ID=true)  耗時 : 51657 ms    平均每秒 : 1935846
          JNI 字段讀取 (緩存Class=true ,緩存字段ID=true)   耗時 : 2187 ms     平均每秒 : 45724737

          java.version = 1.4.2_19
          JNI 字段讀取 (緩存Class=false ,緩存字段ID=false) 耗時 : 97500 ms    平均每秒 : 1025641
          JNI 字段讀取 (緩存Class=true ,緩存字段ID=false)  耗時 : 38110 ms    平均每秒 : 2623983
          JNI 字段讀取 (緩存Class=false ,緩存字段ID=true)  耗時 : 55204 ms    平均每秒 : 1811462
          JNI 字段讀取 (緩存Class=true ,緩存字段ID=true)   耗時 : 4187 ms     平均每秒 : 23883448

           查找class和ID(field和method)消耗大量的時間。只是讀取字段值的時間基本上跟上面的JNI空方法是一個數(shù)量級。
           而如果每次都根據(jù)名稱查找class和field的話,性能要下降高達(dá)40倍。
           讀取一個字段值的性能在百萬級上,在交互頻繁的JNI應(yīng)用中是不能忍受的。
           消耗時間最多的就是查找class,因此在Native里保存class和member id是必要的。
           class和member id在一定范圍內(nèi)是穩(wěn)定的,但在動態(tài)加載的class loader下,保存全局的class要么可能失效,要么可能造成無法卸載classloader,
           在諸如OSGI框架下的JNI應(yīng)用還要特別注意這方面的問題。

           在讀取字段值和查找FieldID上,jdk1.4和1.5、1.6的差距是非常明顯的。但在最耗時的查找class上,三個版本沒有明顯差距。

           

           

          基于線程變量(TlsSetValue/TlsGetValue)的JNIEnv讀取和基于JavaVM的JNIEnv讀取(JavaVM.GetEnv)

          JNIEnv讀取 (線程變量)   耗時 : 516 ms      平均每秒 : 193798449

          java.version = 1.6.0_14
          JNIEnv讀取 (JavaVM)     耗時 : 1985 ms     平均每秒 : 50377833

          java.version = 1.5.0_04
          JNIEnv讀取 (JavaVM)     耗時 : 2218 ms     平均每秒 : 45085662

          java.version = 1.4.2_19
          JNIEnv讀取 (JavaVM)     耗時 : 2234 ms     平均每秒 : 44762757


          為什么要做這個JNIEnv讀取測試:
           JavaVM是進(jìn)程全局有效的,而JNIEnv是線程相關(guān)的,
           但JNI編程是可以不用這樣的模式來獲得JNIEnv的,需要在所有相關(guān)的函數(shù)調(diào)用里帶JNIEnv參數(shù)。
           在C++編程模式下,大量的對象方法調(diào)用都要帶JNIEnv的參數(shù)確實不如動態(tài)獲得它方便。
           在性能可以接受的范圍內(nèi)是可以考慮用其他的模式來隨時獲得JNIEnv的。因此我才會做這個測試。

           從上面的測試數(shù)據(jù)看,用線程變量的性能是優(yōu)于JavaVM.GetEnv的,而且從相對的數(shù)量級上看,個人認(rèn)為是完全可以接受這種JNIEnv的獲得模式的。

           

          希望以上的測試分析對大家的JNI應(yīng)用開發(fā)和優(yōu)化有一定的參考價值。

           

          posted on 2009-09-17 05:39 TaoLei 閱讀(4175) 評論(2)  編輯  收藏

          FeedBack:
          # re: jni的幾個基本的性能測試分析 2010-02-24 17:03 rt
          感想LZ,支持原創(chuàng)。  回復(fù)  更多評論
            
          # re: jni的幾個基本的性能測試分析 2012-12-31 16:55 tb
          老大,
          基于線程變量(TlsSetValue/TlsGetValue)的JNIEnv讀取,這個方式怎么使用啊???

          看你的測試結(jié)果比基于JavaVM的JNIEnv讀取(JavaVM.GetEnv)這個方法給力啊....學(xué)習(xí)下....老大多多指教啊...  回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 锦屏县| 瓮安县| 山阴县| 武平县| 卫辉市| 古浪县| 正阳县| 榆中县| 科尔| 灵丘县| 巴彦淖尔市| 峨眉山市| 临城县| 奈曼旗| 凌海市| 文成县| 长治县| 榆林市| 赤壁市| 嘉荫县| 涿州市| 达州市| 安溪县| 张掖市| 潞西市| 化德县| 汝城县| 鄂尔多斯市| 凉山| 滨州市| 宽甸| 丽水市| 长阳| 保德县| 项城市| 沙坪坝区| 宁夏| 永济市| 泉州市| 寻乌县| 武平县|