简体   繁体   中英

String Concat Speed In Java

I was prototyping an SQL query quickly, and instead of doing it the correct way, I just decided to slam through it with a bunch of string concats, the entire time thinking that this would be extremely slow, but it didn't matter because I was just testing the query. To my suprise, Java says that this code take 0 ms to complete? Doesn't it take more time do this with + rather than StringBuilder or similar?

long t = System.currentTimeMillis();
String load = "";
for (String s : loadFields)
    load += s + ", ";

String sql = "SELECT ";
sql += load + "sum(relevance) AS 'score' " +
        "FROM ( ";

for (int i = 0; i < searchFields.length; i++) {
    sql += "SELECT ";
    sql += load;
    sql += rels[i] + " AS relevance FROM articles WHERE " +
            searchFields[i];

    sql += " LIKE '%" + terms[0] + "%' ";
    for (int z = 1; z < terms.length; z++)
        sql += "AND " + searchFields[i] + " LIKE '%" + terms[z] + "%' ";

    if (i != searchFields.length - 1) sql += " UNION ALL ";
}

sql += ") results GROUP BY " + load.substring(0, load.length() - 2) + " ";
sql += "ORDER BY score desc, date desc";
System.out.println("Build Time: " + (System.currentTimeMillis() - t) + " ms");

Yes, this is very ugly, but the point is not to iterpret the SQL, but to tell me why this is so fast.

Build Time: 0 ms

Edit: I ran the test 10000 times with 20 terms, and it took about 10 seconds, so about 1/10 of a millisecond. Now that I think about it, it is pretty obvious that this isn't that much to computation unless I start getting really long strings.

You're only doing 29 concatenations - I should hope that takes less than a millisecond.

If you want to test this code against a StringBuilder implementation, you should iterate it 10,000 times or so (and do proper JVM warm-up).

Benchmark

I was curious to see what the exact difference is in this case, so I converted your code to use .concat() and StringBuilder and benchmarked with 10,000 iterations (2,000 warmup), with 5 fields and 20 terms, all of them randomly generated 32 char strings.

Results (in milliseconds):

   plus: 19656 (0.5/ms)
 concat: 5656  (1.77/ms)
builder: 578   (17.3/ms)

The strings you are concatenating are very short. Try using strings of length 100,000 or more (write some code to generate huge strings) and then do that several hundred times. With short strings and only a few concats, the difference is too small to be measurable.

You are measuring the time using the millisecond clock.

  • The absolute smallest interval that you can measure is one millisecond. That is typically OVER ONE MILLION cycles of the hardware clock. A current generation CPU can do an lot of computation in that time.

  • It is possible that the actual granularity of the millisecond is a number of milliseconds. (Unlikely with a current generation OS, but I remember the days when the clock tick was 20 milliseconds.)

Either way, it is not surprising that the measured time is usually zero.


To get a meaningful measurement, you need to put a loop around that code and run it hundreds of thousands of times. And put another loop around that to run the test repeatedly... until the measured time stabilizes.

Finally, this is going to be allocation intensive, and you need to include the amortized GC times. (An optimized version using StringBuilder will win in part by NOT being so allocation intensive.)

It is my understanding that doing + means that java is creating a copy of your original string and adding the new part to the copy everytime. I would think that would be slower but in any case it would definintly seem to take more memory than StringBuilder . It seems that it would be much more efficient to have a StringBuilder that you kept adding to and only .toString or String.valueOf() when you are done adding things.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM