簡體   English   中英

壓縮字符串時的程序效率與使用原始字符串進行編輯的新字符串

[英]Program efficency when contracting Strings vs making a new String w/ edits to the original one

我只是想知道以下兩個代碼的效率:

public void appendInput(String s, boolean isCommand) {

    s = "\n" + (isCommand == true ? ">" : "") + s + "\n";
    getConsoleInput().append(s);

    //vs

    getConsoleInput().append("\n" + (isCommand == true ? ">" : "") + s + "\n");

}

根據我對這種語言的基本了解,第二種語言是否會比第二種版本更高效,因為它不會創建新的對象( String )? 還是在收縮兩個String時創建一個新的String 我認同。 我只需要一個比我更了解Java的人。

因此,我決定進行一些測試。 這是我想出的:

public class Main {

public static void main(String[] args) {
    String s;
    Boolean b;
    long startTime;
    long endTime;
    long[] results = new long[4];

    System.out.println("*ALL TESTS WILL BE LOOPED *1000");

    sep();

    System.out.println("METHOD 1;-- TEST 1 - STRING = \"TESTING \" && BOOLEAN = FALSE:");

    s = "TESTING";
    b = false;  // change variables

    startTime = System.currentTimeMillis(); //commence testing from here

    for(int i = 0; i < 1000; i ++) {
        s = "" + (b ? ">" : "") + s + "";
        System.out.print(s);
    }

    endTime = System.currentTimeMillis();
    results[0] = endTime - startTime;
    System.out.println("Total execution time: " + results[0] + "ms");

    sep();

    //Next test

    System.out.println("METHOD 1;-- TEST 2 - STRING = \"TESTING \" && BOOLEAN = TRUE:");

    s = "TESTING";
    b = false;

    startTime = System.currentTimeMillis();

    for(int i = 0; i < 1000; i ++) {
        s = "" + (b ? ">" : "") + s + "";
        System.out.print(s);
    }

    endTime = System.currentTimeMillis();
    results[1] = endTime - startTime;
    System.out.println("Total execution time: " + results[1] + "ms");
    sep();

    //Next test

    System.out.println("METHOD 2;-- TEST 1 - STRING = \"TESTING \" && BOOLEAN = FALSE:");

    s = "TESTING";
    b = false;  // change variables

    startTime = System.currentTimeMillis(); //commence testing from here

    for(int i = 0; i < 1000; i ++) {
        System.out.print("" + (b == true ? ">" : "") + s + "");
    }

    endTime = System.currentTimeMillis();
    results[2] = endTime - startTime;
    System.out.println("Total execution time: " + results[2] + "ms");
    sep();

    //Next test

    System.out.println("METHOD 2;-- TEST 2 - STRING = \"TESTING \" && BOOLEAN = TRUE:");

    s = "TESTING";
    b = false;

    startTime = System.currentTimeMillis();

    for(int i = 0; i < 1000; i ++) {
        System.out.print("" + (b == true ? ">" : "") + s + "");
    }

    endTime = System.currentTimeMillis();
    results[3] = endTime - startTime;
    System.out.println("Total execution time: " + results[3] + "ms");
    sep();

    System.out.println("RESULTS:");
    System.out.println("-----------------------");

    String[] typesOfTests = {"METHOD 1 BOOLEAN = FALSE", "METHOD 1 BOOLEAN = TRUE  ",
            "METHOD 2 BOOLEAN = FALSE", "METHOD 2 BOOLEAN = TRUE  "};

    for(int i = 0; i < typesOfTests.length && i < results.length; i++) {
        System.out.print(typesOfTests[i]);
        System.out.print("\t");
        System.out.println(results[i]);
    }
}

private static void sep() {
    System.out.println("====================================");
}
private void optOne(String s, boolean b) {
    s = "\n" + (b == true ? ">" : "") + s + "\n";
    System.out.println(s);
}

private void optTwo(String s, boolean b) {
    System.out.println("\n" + (b == true ? ">" : "") + s + "\n");

}

}

這是一些結果...

ALL TESTS WILL BE LOOPED *1000
====================================
METHOD 1;-- TEST 1 - STRING = "TESTING " && BOOLEAN = FALSE:
TESTING *1000 ...
Total execution time: 25ms
====================================
METHOD 1;-- TEST 2 - STRING = "TESTING " && BOOLEAN = TRUE:
TESTING *1000 ...
Total execution time: 17ms
====================================
METHOD 2;-- TEST 1 - STRING = "TESTING " && BOOLEAN = FALSE:
TESTING *1000 ...
Total execution time: 4ms
====================================
METHOD 2;-- TEST 2 - STRING = "TESTING " && BOOLEAN = TRUE:
TESTING *1000 ...
Total execution time: 8ms
====================================
RESULTS:
-----------------------
METHOD 1 | BOOLEAN = FALSE  | 25
METHOD 1 | BOOLEAN = TRUE   | 17
METHOD 2 | BOOLEAN = FALSE  | 4
METHOD 2 | BOOLEAN = TRUE   | 8

和其他一些(OK,OK,僅表!)

METHOD 1 | BOOLEAN = FALSE  | 19
METHOD 1 | BOOLEAN = TRUE   | 10
METHOD 2 | BOOLEAN = FALSE  | 5
METHOD 2 | BOOLEAN = TRUE   | 5

METHOD 1 | BOOLEAN = FALSE  | 18
METHOD 1 | BOOLEAN = TRUE   | 11
METHOD 2 | BOOLEAN = FALSE  | 5
METHOD 2 | BOOLEAN = TRUE   | 4

METHOD 1 | BOOLEAN = FALSE  | 20
METHOD 1 | BOOLEAN = TRUE   | 16
METHOD 2 | BOOLEAN = FALSE  | 6
METHOD 2 | BOOLEAN = TRUE   | 4

結論:

方法1( s = "" + (b ? ">" : "") + s + ""; System.out.print(s); )比方法2( System.out.print("" + (b == true ? ">" : "") + s + ""); ),因為無需創建新的String對象。

我注意到的另一個趨勢是,在兩種方法中,當boolean值為false ,時間增加了三分之一以上,即使方法1中的時間比方法2中的時間更引人注目。我不知道為什么這是...有人可以向我解釋嗎?


TL; DR方法1較慢,因為需要創建一個新的String對象。 此外,當boolean等於false時,兩種情況下執行方法所花費的時間都會增加。 你能給我解釋一下嗎?

由於JVM的工作原理,“徒手編寫”基准幾乎沒有用。 您可以得到變化很大的結果。 可行的方法是,當字節碼由JVM正確優化時,將代碼運行很多次,這是在運行該代碼一段時間后發生的。 JMH框架是關於什么的。 如果您需要正確地對代碼進行基准測試,請務必使用它,尤其是對於諸如您的微基准測試。

因此,我自己進行了一些測試(只需看看使用JMH可使代碼變得更簡單):

package org.sample;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.infra.Blackhole;

public class StringsAppendBenchmark {
    private static String TESTING = "TESTING";

    @Benchmark
    @Fork(3)
    public void withVariable(Blackhole bh) {
        String s = "\n" + ">" + TESTING + "\n";
        bh.consume(s);
    }

    @Benchmark
    @Fork(3)
    public void withoutVariable(Blackhole bh) {
        bh.consume( "\n" + ">" + TESTING + "\n" );
    }
}

現在,使用System.out.println()進行基准測試不是很有用,因為產生的性能在很大程度上取決於讀取應用程序的stdout 寫入/ dev / null在時間上可以忽略不計,而寫入IDE控制台可能會很快耗盡所有內存,而讓您等待系統換出。 這就是為什么使用Blackhole的原因, Blackhole只是接受一個參數而對它不執行任何操作,因為該參數不會通過JVM中的運行時字節碼優化而被優化為不存在。

運行基准輸出:

Benchmark                                      Mode  Samples         Score         Error  Units
o.s.StringsAppendBenchmark.withVariable       thrpt       60  37105629.065 ± 1124455.355  ops/s
o.s.StringsAppendBenchmark.withoutVariable    thrpt       60  38059994.264 ± 1021414.039  ops/s

結果和誤差范圍向我們表明,是否事先將其存儲在變量中都沒有關系。 正如預期的那樣,老實說。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM