Kotlin、Java、C#、およびNimでの配列クリア方法のパフォーマンステスト

起因

私のプロジェクトの1つはKotlinで記述されています。彼は多次元データベースアプリケーションであるため、int配列を非常に頻繁に操作します。プログラムのセグメントがある場合、次のコードのように、何億もの配列クリアアクションを実行する必要があります。

Arrays.fill(target、0);

このArrays.fillは実際にはjdkの実装であり、非常に単純です。データを埋めるためのforループです。

したがって、私は彼を改善したいと思います。たとえば、8つの長さをクリアする方法は、次のとおりです。

fun clear8(target:IntArray){
     if(target.size <8 ){
         throw IndexOutOfBoundsException()
    } 
    target [ 0] = 0 
    target [ 1] = 0 
    target [ 2] = 0 
    target [ 3] = 0 
    target [ 4] = 0 
    ターゲット[ 5] = 0 
    ターゲット[ 6] = 0 
    ターゲット[ 7] = 0 
}

あなたの目を疑わないでください、そのような文章は通常効果的です。良いコンパイラーは私が書いたコードを最適化するでしょう、もちろん、より良いコンパイラーは単純な配列のforループを最適化します。

次に、テストしてみましょう。

import java.util。*
 import kotlin.system.measureNanoTime 

fun main(){ test3 
    ()
} 


private fun test3(){ 
    val size = 8 
    val time2 = measureNanoTime { 
        val target = IntArray(size)
         for(i in 0 to 10_0000_0000 ){ 
            IntArrays.clear8(target)
        } 
    } 
    println( "fill $ size $ time2" 

    val time1 = measureNanoTime { 
        val target = IntArray(size)
         for(i in 010_0000_0000まで){ 
            Arrays.fill(target、 0 
        } 
    } 
    println( "Arrays.fill $ size $ time1" 
    println()
} 

内部オブジェクトIntArrays { 
    fun clear8(target:IntArray){ 
        if(target.size <8 ) {
             throw IndexOutOfBoundsException()
        } 
        target [ 0] = 0 
        target [ 1] = 0 
        target [ 2] = 0 
        target [ 3] = 0 
        target [ 4] = 0 
        target [ 5] = 0 
        target [ 6] = 0
        target [ 7] = 0 
    } 
}

テスト結果:

fill8 55,408,200アレイ
.fill8 2,262,171,100

展開メソッドを使用すると、パフォーマンスは、Javaに付属している2.2秒の40倍であることがわかります。

Javaとのパフォーマンス比較

Kotlinのコンパイラーは本当に強力だと嘆いていますが、慎重に検討してください。正しくありません。KotlinはJVMに基づいているため、Javaの仮想マシンランタイムは非常に強力である必要があります。このプログラムをJavaに変換する場合は、直接記述する方が適切です。高速で、少なくとも一貫したパフォーマンス。やるだけ。

// IntArrays.java 
import java.util.Arrays; 

最終 クラスIntArrays {
     static  void clear8(int [] target){
 / *         if(target.length <8){ 
            throw new IndexOutOfBoundsException(); 
        } * / 
        target [ 0] = 0 ; 
        target [ 1] = 0 ; 
        target [ 2] = 0 ; 
        target [ 3] = 0 ; 
        target [ 4] = 0 ; 
        target [ 5] = 0 ; 
        target [ 6] = 0 ;
        target [ 7] = 0 ; 
    } 
} 

// IntArraysDemoJava.java 
import java.util.Arrays; 

public  final  class IntArraysDemoJava {
     public  static  void main(String [] var0){ 
        test1(); 
    } 

    private  static  void test1(){
         long count = 1000000000 ;
        長いスタート= System.nanoTime();
        final  int [] target = new  int [8 ]; 

        forinti = 0; i <カウント; i ++ ){ 
            IntArrays.clear8(target); 
        } 
        long time2 = System.nanoTime()- 開始; 
        System.out.println( "fill8" + time2); 

        start = System.nanoTime();
        forint i = 0; i <count; i ++ ){ 
            Arrays.fill(target、 0 ); 
        } 

        long time1 = System.nanoTime()- 開始; 
        System.out.println( "Arrays.fill8" + time1); 
        System.out.println(); 
    } 
}
Java実装

テスト結果は次のとおりです。

fill8 2,018,500,800アレイ
.fill8 2,234,306,500

この種の最適化はJavaではほとんど効果がありません。リリースコンパイルパラメータの概念は見つかりませんでした。せいぜい、debug = falseしかありません。gradleに含めました。

compileJava { 
    options.debug = false 
}

つまり、Kotlinによって生成されたバイトコードがJavaによって生成されたバイトコードよりも優れているということです。

Java Kotlin 
ALOAD 0 ALOAD 1 
ICONST_0 ICONST_0 
ICONST_0 ICONST_0 
IASTORE ASTORE 
  
ALOAD 0 ALOAD 1 
ICONST_1 ICONST_1 
ICONST_0 ICONST_0 
IASTORE IASTORE

バイトコードは少し違うのですが、なぜかと聞かれると?私の編。

Cとの比較#

.netの熱狂的なファンとして、今回は.netコア3が多くのパフォーマンス最適化を行ったことは言うまでもなく、c#の方が速いかどうかを考えます。

クラスProgram {
    static  void Main(string [] args){ 
       Test3.test1(); 
   } 
} 

クラスTest3 
{ 
    public  static  void test1()
    { 
        long count = 1000000000 ;
        var watch = System.Diagnostics.Stopwatch.StartNew();
        int [] target = new  int [ 8 ]; 

        forint i = 0 ; i <count; i ++ 
        { 
            Clear8(target); 
        } 
        watch.Stop(); 
        Console.WriteLine(" fill8           " + watch.Elapsed); 

        watch.Restart(); 
        以下のためにINT iが= 0 ; I <数; I ++ 
        { 
            Array.Clear(ターゲット、08 )。
        } 

        watch.Stop(); 
        Console.WriteLine(" Array.Clear8    " + watch.Elapsed); 
        Console.WriteLine(); 
    } 

    static  void Clear8(int [] target)
    {
        / *if(target.Length <8)
        { 
            throw new IndexOutOfRangeException(); 
        } * / 
        target [ 0 ] = 0 ; 
        target [ 1 ] = 0 ; 
        target [ 2 ] = 0 ; 
        target [ 3 ] = 0 ; 
        target [ 4 ] = 0 ; 
        target [ 5 ] = 0 ; 
        target [ 6 ] = 0 ; 
        ターゲット[ 7 ] = 0; 
    } 
}

テスト結果:

fill8 00:00:02.7462676
Array.Clear8 00:00:08.4920514

Javaと比較すると、速度はさらに遅く、システムに付属するArray.clearもさらに遅くなります。これにより、どうすれば耐えられるのか、Span.Fill(0)を使用すると、結果はさらに不十分になります。

Nimと比較したパフォーマンス

興味が言及され、それを達成するためにC言語を使用します...書かれていません、私は愚かです...そして、Rustを使用して実装するか、実現されていません。まだ完了していません...

最後に、Nim環境を捨てる、ええと、それはまだ簡単です。

インポート時間、strutils 

proc clear8 * [int](target:var seq [int])= 
    target [0] = 0 
    target [ 1] = 0 
    target [ 2] = 0 
    target [ 3] = 0 
    target [ 4] = 0 
    target [ 5] = 0 
    target [ 6] = 0 
    target [ 7] = 0 

proc clear * [int](target:var seq [int])=
     for i in 0 .. < target.len:
        target [i] = 0 


proc test3() =
    const size = 8 
    var start = epochTime()
    var target = newseq [int](size)
     for i in 0 .. < 10_0000_0000:
        target.clear8()
    
    letlapsedStr =(epochTime()-start).formatFloat(format = ffDecimal 、精度= 3 
    echo " fill8          " 、expededStr 

    start = epochTime()
     for i in 0 .. < 10_0000_0000:
        target.clear()
    
    letlapsedStr2=(epochTime()-start).formatFloat(format = ffDecimal、precision = 3 
    echo " Arrays.fill    " 、lapsedStr2 test3 

()
それは

テスト結果については、-releaseパラメータの追加に注意してください。

fill8 3.499
Arrays.fill 5.825

失望、そしてその失望。

備考

すべてのテストはデスクトップコンピューターで行われ、構成は次のとおりです。

AMD Ryzen 5 3600 6コア3.59 Ghz

8 GBのRAM

Windows 10 64 Professional Edition

すべてのテストはreleaseを使用してコンパイルされています。

おすすめ

転載: www.cnblogs.com/tansm/p/12684664.html