Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java不可变类的速度要慢得多_Java_Performance_Immutability - Fatal编程技术网

java不可变类的速度要慢得多

java不可变类的速度要慢得多,java,performance,immutability,Java,Performance,Immutability,我需要一些复杂的数学库,所以我在使用不可变复杂的库和使用可变复杂的库之间犹豫不决。显然,我希望计算运行得相当快(除非它破坏了可读性等) 因此,我创建了速度可变与不可变的简单测试: final class MutableInt { private int value; public int getValue() { return value; } public void setValue(int value) { this.val

我需要一些复杂的数学库,所以我在使用不可变复杂的库和使用可变复杂的库之间犹豫不决。显然,我希望计算运行得相当快(除非它破坏了可读性等)

因此,我创建了速度可变与不可变的简单测试:

final class MutableInt {
    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public MutableInt() {
        this(0);
    }

    public MutableInt(int value) {
        this.value = value;
    }   
}

final class ImmutableInt {
    private final int value;

    public ImmutableInt(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public class TestImmutableSpeed {

    static long testMutable(final int arrLen) {
        MutableInt[] arrMutable = new MutableInt[arrLen];
        for (int i = 0; i < arrMutable.length; ++i) {
            arrMutable[i] = new MutableInt(i);
            for (int j = 0; j < arrMutable.length; ++j) {
                arrMutable[i].setValue(arrMutable[i].getValue() + j);
            }
        }
        long sumMutable = 0;
        for (MutableInt item : arrMutable) {
            sumMutable += item.getValue();
        }
        return sumMutable;
    }

    static long testImmutable(final int arrLen) {
        ImmutableInt[] arrImmutable = new ImmutableInt[arrLen];
        for (int i = 0; i < arrImmutable.length; ++i) {
            arrImmutable[i] = new ImmutableInt(i);
            for (int j = 0; j < arrImmutable.length; ++j) {
                arrImmutable[i] = new ImmutableInt(arrImmutable[i].getValue() + j);
            }
        }
        long sumImmutable = 0;
        for (ImmutableInt item : arrImmutable) {
            sumImmutable += item.getValue();
        }
        return sumImmutable;
    }

    public static void main(String[] args) {
        final int arrLen = 1<<14;

        long tmStart = System.nanoTime();
        System.out.println("sum = " + testMutable(arrLen));
        long tmMid = System.nanoTime();
        System.out.println("sum = " + testImmutable(arrLen));
        long tmEnd = System.nanoTime();

        System.out.println("speed comparison mutable vs immutable:");
        System.out.println("mutable   " + (tmMid - tmStart)/1000000 + " ms");
        System.out.println("immutable " + (tmEnd - tmMid)/1000000 + " ms");
    }
}
final类MutableInt{
私有int值;
public int getValue(){
返回值;
}
公共无效设置值(int值){
这个值=值;
}
公共可变int(){
这(0);
}
公共可变整型(整型值){
这个值=值;
}   
}
最终类不可变{
私有最终整数值;
公共不可变int(int值){
这个值=值;
}
public int getValue(){
返回值;
}
}
公共类TestImmutableSpeed{
静态长测试可变(最终整数arrLen){
MutableInt[]arrMutable=新的MutableInt[arrLen];
对于(int i=0;ifinal int arrLen=1不可变的值使Java编程变得更干净。您不必到处复制,以避免以远距离的怪异动作结束(我的意思是在一个地方更改值会无意中更改另一个地方的值)。删除副本会加快某些地方的速度,但创建新实例会降低其他地方的速度

(C++的有趣之处在于它采用了相反的方法。您可以在定义良好的点获得副本,而无需编写任何代码。实际上,您必须编写代码才能删除副本。)

如果您关心的是性能,那么可变的复杂数组也不好。最好是有一个复杂数组类,该类使用隐藏在实现中的单个双数组,或者只使用双数组raw

早在上世纪90年代,Guy Steele就提到了向Java添加值类型的想法,这是使Java语言本身完整的一部分
structs C#后来被引入,但两者都不能处理Java中最明显的值类string。

这很有趣。首先,这不是一个公平的测试;当你这样做时,你没有预热JVM。基准测试通常很难做到。我重构了你的代码以供使用,得到了相似但不同的结果结果:immutable类的速度仅慢了3倍。目前还不确定原因。总之,到目前为止的工作如下:

TestImmutableSpeed.java 字符串更新 因此我考虑了更多,决定尝试将包装类从
int
更改为对象,在本例中为
String
。将静态类更改为
String
s,并使用
Integer.valueOf(I).toString()加载字符串
,而不是将它们添加到
StringBuilder
中,我得到了以下结果:

 0% Scenario{vm=java, trial=0, benchmark=Immutable} 11034616.91 ns; σ=7006742.43 ns @ 10 trials
50% Scenario{vm=java, trial=0, benchmark=Mutable} 9494963.68 ns; σ=6201410.87 ns @ 10 trials

benchmark    ms linear runtime
Immutable 11.03 ==============================
  Mutable  9.49 =========================

vm: java
trial: 0

但是,我认为在这种情况下,差异主要在于必须进行的所有数组复制,而不是使用
String
s这一事实。

不变性有时会带来速度损失。如果速度重要,请使用具有可变复杂度的数学库。

是否可以在不使用时发布相同长度数组的结果使用Caliper?查看它是否没有使可变版本的运行速度变慢(总毫秒)。我使用了优化参数,其中一些参数使jvm在可变和可变版本中的运行速度变慢(但在这种情况下,可变版本的运行速度并没有变快多少)@PEANUT我不明白你的要求,你没有使用卡钳就已经这么做了。卡钳自动使用相同的数组长度运行测试;事实上,在预热JVM后,它在不同的长度下运行了10次。你的计算机有不同的速度。我只是想看看结果,如果你使用我在问题中列出的参数运行JVM,如果卡钳使它运行得更快(因此我的测试有误),或者没有(卡钳有误)。我还没有使用卡钳的经验,他们的wiki现在已经过时了,所以我不能亲自尝试。@Pineut不幸的是,我必须回去工作了。它可以在maven上使用,你可以在这里手动下载:谢谢,我测试过它,它确实比这个基准慢3倍,而不是15倍。所以,基本上,Java中的可变速度很慢,但不可变E是非常慢的?@ PeNUUT用于数值工作,爪哇中的小对象通常很慢。即使在C或C++中,通常在一个数组中分配大量小值而不是单独堆分配,尽管在堆栈上放置小对象的效果很好。霍廷:C/C++版本更快,因为您可以创建值数组,我不能想象为什么会有人在C++中堆堆,例如我在问题中提供的。哦,我应该注意到我加了1,因为它是好的点,我同意测试int []的速度和MutabLINT的速度[]。它的速度几乎是一样的。MutableInt非常快(只需要多一点内存)。是的,这就是为什么 import com.google.caliper.Runner; import com.google.caliper.SimpleBenchmark; final class MutableInt { private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public MutableInt() { this(0); } public MutableInt(int value) { this.value = value; } } final class ImmutableInt { private final int value; public ImmutableInt(int value) { this.value = value; } public int getValue() { return value; } } public class TestImmutableSpeed extends SimpleBenchmark { static long testMutable(final int arrLen) { MutableInt[] arrMutable = new MutableInt[arrLen]; for (int i = 0; i 0% Scenario{vm=java, trial=0, benchmark=Mutable, type=-server, minMemory=-Xms256m, optimizations=-XX:+AggressiveOpts} 91614044.60 ns; ?=250338.20 ns @ 3 trials 50% Scenario{vm=java, trial=0, benchmark=Immutable, type=-server, minMemory=-Xms256m, optimizations=-XX:+AggressiveOpts} 1108057922.00 ns; ?=3920760.98 ns @ 3 trials benchmark ms linear runtime Mutable 91.6 == Immutable 1108.1 ============================== 0% Scenario{vm=java, trial=0, benchmark=Mutable} 516562214.00 ns; ?=623120.57 ns @ 3 trials 50% Scenario{vm=java, trial=0, benchmark=Immutable} 1706758503.00 ns; ?=5842389.60 ns @ 3 trials benchmark ms linear runtime Mutable 517 ========= Immutable 1707 ==============================
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class TestImmutableSpeed {
    static final class MutableInt {
        private int value;

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public MutableInt() {
            this(0);
        }

        public MutableInt(int value) {
            this.value = value;
        }   
    }

    static final class ImmutableInt {
        private final int value;

        public ImmutableInt(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }
    }

    public static class TestBenchmark extends SimpleBenchmark {
        public void timeMutable(final int arrLen) {
            MutableInt[] arrMutable = new MutableInt[arrLen];
            for (int i = 0; i < arrMutable.length; ++i) {
                arrMutable[i] = new MutableInt(i);
                for (int j = 0; j < arrMutable.length; ++j) {
                    arrMutable[i].setValue(arrMutable[i].getValue() + j);
                }
            }
            long sumMutable = 0;
            for (MutableInt item : arrMutable) {
                sumMutable += item.getValue();
            }
            System.out.println(sumMutable);
        }

        public void timeImmutable(final int arrLen) {
            ImmutableInt[] arrImmutable = new ImmutableInt[arrLen];
            for (int i = 0; i < arrImmutable.length; ++i) {
                arrImmutable[i] = new ImmutableInt(i);
                for (int j = 0; j < arrImmutable.length; ++j) {
                    arrImmutable[i] = new ImmutableInt(arrImmutable[i].getValue() + j);
                }
            }
            long sumImmutable = 0;
            for (ImmutableInt item : arrImmutable) {
                sumImmutable += item.getValue();
            }
            System.out.println(sumImmutable);
        }
    }

    public static void main(String[] args) {
        Runner.main(TestBenchmark.class, new String[0]);
    }
}
 0% Scenario{vm=java, trial=0, benchmark=Immutable} 78574.05 ns; σ=21336.61 ns @ 10 trials
 50% Scenario{vm=java, trial=0, benchmark=Mutable} 24956.94 ns; σ=7267.78 ns @ 10 trials

 benchmark   us linear runtime
 Immutable 78.6 ==============================
   Mutable 25.0 =========

 vm: java
 trial: 0
 0% Scenario{vm=java, trial=0, benchmark=Immutable} 11034616.91 ns; σ=7006742.43 ns @ 10 trials
50% Scenario{vm=java, trial=0, benchmark=Mutable} 9494963.68 ns; σ=6201410.87 ns @ 10 trials

benchmark    ms linear runtime
Immutable 11.03 ==============================
  Mutable  9.49 =========================

vm: java
trial: 0