[英]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.