开发者

What's could be the right test case for evaluating assignment operators performance vs concrete operations?

开发者 https://www.devze.com 2023-01-10 18:08 出处:网络
Simply I am trying to figure out what is the fast way to assign a value like somevar+=1; or somevar=somevar+1;

Simply I am trying to figure out what is the fast way to assign a value like

somevar+=1;

or

somevar=somevar+1;

time ago in situations with text instead of integers I encountered some performance decrease using text+="sometext" instead of text.append("sometext") or text=text+"sometext", the problem is that I did not find anymore the source code where I annotated my considerations. So theoretically what's the fastest way?

The code开发者_开发技巧 background is set into a fast loop, nearly real time.


If you have something like this:

Collection<String> strings = ...;
String all = "";
for (String s : strings) all += s;

... then it's equivalent to:

Collection<String> strings = ...;
String all = "";
for (String s : strings) all = new StringBuilder(all).append(s).toString();

Each loops creates a new StringBuilder which is essentially a copy of all, appends a copy of s to it, and then copies the result of the concatenation to a new String. Obviously, using a single StringBuilder saves a lot of unnecessary allocations:

Collection<String> strings = ...;
StringBuilder sb = new StringBuilder();
for (String s : strings) sb.append(s);
String all = sb.toString();

As for x += y versus x = x + y, they compile to the same thing.

class Concat {

        public String concat1(String a, String b) {
                a += b;
                return a;
        }

        public String concat2(String a, String b) {
                a = a + b;
                return a;
        }

}

Compile it with javac, and then disassemble it with javap:

$ javap -c Concat
Compiled from "Concat.java"
class Concat extends java.lang.Object{
Concat();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public java.lang.String concat1(java.lang.String, java.lang.String);
  Code:
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   aload_1
   8:   invokevirtual   #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   11:  aload_2
   12:  invokevirtual   #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   15:  invokevirtual   #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   18:  astore_1
   19:  aload_1
   20:  areturn

public java.lang.String concat2(java.lang.String, java.lang.String);
  Code:
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   aload_1
   8:   invokevirtual   #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   11:  aload_2
   12:  invokevirtual   #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   15:  invokevirtual   #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   18:  astore_1
   19:  aload_1
   20:  areturn

}

Personally, I'd favor += because with it, you make a clearer statement of intent - "I want to add the content of b to a". Any variations in performance between the two forms are with a 100% certainty the result of something outside of your code (e.g., GC pauses, random cache misses or something like it).

Bad compilers might also have a slightly easier time to optimize the += form (which is irrelevant to you, since even if javac would be crappy, HotSpot sure isn't).


Strings are immutable. Hence, concatenating 2 Strings causes a new String object to be created. Using StringBuilder will gain you a lot of performance.

However, primitive numeric types are not immutable and not heap allocated. Whatever you do with them tends to be really fast no matter what :)


String 'arithmetics' internal are rather complicated - just because they happen quite often and the compilers tries to optimize whereever it can.

First of all, append("something") is not a String method. It is a method from the StringBuffer or StringBuilder class.

The other expressions are quite equivalent. I'm pretty sure one can't look at the pattern and decide that one is faster in general.

In General and because Strings are immutable, a concatenation will create a new String for each String literal, a new String for each intermediate result and one new String for the result. So this

String s = "one" + "two" + "three";

will require five String objects ("one", "two", "three", "onetwo", "onwtwothree").

The first compiler optimization is 'interning' the literals. In short: "one", "two" and "three" are not created but reused.

A second compiler optimization is replacing the String addition by StringBuilder operation (if it makes sense). So the concatenation could be replaced by

StringBuilder sb = new StringBuilder("one");
sb.append("two");
sb.append("three");
String s = sb.toString();

(just to illustrate - a real compiler might not use the strategy for this example code, it might concatenate the the literals during compilation already...)

0

精彩评论

暂无评论...
验证码 换一张
取 消