字符串Concat速度在Java中

时间:2011-06-09 04:05:07

标签: java performance string

我正在迅速对SQL查询进行原型设计,而不是以正确的方式进行,我只是决定用一堆字符串连接来抨击它,整个时间都认为这会非常慢,但它没有因为我只是在测试查询。令我惊讶的是,Java说这段代码需要0毫秒才能完成?使用+而不是StringBuilder或类似内容时,是否需要花费更多时间?

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");

是的,这非常难看,但问题不在于预测SQL,而是告诉我为什么这么快。

Build Time: 0 ms

编辑:我用20个术语运行了10000次测试,大约花了10秒钟,大约是1/10毫秒。现在我考虑一下,很明显,除非我开始得到很长的字符串,否则计算并不多。

4 个答案:

答案 0 :(得分:9)

你只做了29个连接 - 我希望这个连接时间不到一毫秒。

如果要针对StringBuilder实现测试此代码,则应该迭代10,000次左右(并进行适当的JVM预热)。

基准

我很想知道这种情况下的确切区别是什么,因此我将您的代码转换为使用.concat()StringBuilder并以10,000次迭代(2,000次预热)进行基准测试,其中包含5个字段和20个字段术语,所有这些术语随机生成32个字符串。

结果(以毫秒为单位):

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

答案 1 :(得分:2)

你连接的字符串非常短。尝试使用长度为100,000或更多的字符串(编写一些代码来生成大字符串),然后执行数百次。使用短字符串和只有少数连接,差异太小而无法测量。

答案 2 :(得分:1)

您正在使用毫秒时钟测量时间。

  • 您可以测量的绝对最小间隔为1毫秒。这通常是硬件时钟超过一百万个周期。当前一代CPU可以在那段时间内进行大量计算。

  • 毫秒的实际粒度可能是毫秒数。 (与当前一代操作系统不太一样,但我记得时钟刻度为20毫秒的日子。)

无论哪种方式,测量时间通常为零都不足为奇。


要获得有意义的测量,您需要围绕该代码循环并运行数十万次。然后再绕一圈来重复运行测试......直到测量的时间稳定下来。

最后,这将是分配密集型的,您需要包括摊销的GC时间。 (使用StringBuilder的优化版本将部分地通过NOT分配密集来获胜。)

答案 3 :(得分:1)

我的理解是,执行+意味着java正在创建原始字符串的副本,并且每次都将新部件添加到副本中。我认为这会慢一点,但无论如何它肯定会占用比StringBuilder更多的内存。在您添加内容后,使用StringBuilder并且仅添加.toStringString.valueOf()似乎更有效率。