2010-01-14 27 views
1

哪一個更優化或者有什麼不同?這兩段代碼中的哪一段更好/更快/使用的內存更少?

String s = methodThatReturnsString(); 
int i = methodThatReturnsInt(); 
thirdMethod(s, i); 

thirdMethod(methodThatReturnsString(), methodThatReturnsInt()); 

通過優化我的意思是在內存使用情況等的條件最佳

+18

如果有差異,那就不值得煩惱了。 – Yacoby 2010-01-14 11:54:07

+3

而且所說的區別將取決於所使用的編譯器。編譯器優化甚至可能會導致完全相同的代碼,如果之後沒有使用s和i。我會根據可讀性做出我的決定。 – Stroboskop 2010-01-14 11:55:54

+1

您可以嘗試編譯並比較字節代碼 – lexicalscope 2010-01-14 12:05:35

回答

15

它沒有任何這裏做優化,但它的可讀性的更多問題您代碼...

+2

絕對,但請記住,人們可能會對第一或第二是否更具可讀性持不同意見。 – 2010-01-14 12:11:34

+0

是的,你說得對。但是,這裏仍然是一個可讀性問題;) – romaintaz 2010-01-14 12:32:03

0

完全沒有區別。在這種情況下,您可能需要考慮可讀性和清晰度。

11

哪一個更優化?

的其中一個更容易閱讀:-)

我認爲編譯時的差額優化掉(前提是聲明的變量不使用之後 - 即解決方案,否則相同的)。

-2

thirdMethod(metodThatReturnsString(),metodThatReturnsInt());

更優化...

+1

爲什麼這樣呢? – eljenso 2010-01-14 12:08:02

+0

你可以使用兩個變量s和i,以備將來在同一個程序中使用 – GuruKulki 2010-01-14 12:15:45

+1

yup,如果你不在變量名中,這可能會派上用場...... – Fortega 2010-01-14 12:27:56

1

應該沒有什麼區別。臨時使用的Stringint都必須駐留在某處,Java在內部是堆棧機器。因此,無論您是否給該方法的返回值調用名稱,都必須在執行thirdMethod(String, int)之前將其存儲在堆棧中。

對於生成的JITted代碼的影響可能很難找到。這是一個完全不同的抽象層次。

如果有疑問,簡介。但我不希望這裏有任何不同。

1

這是同樣的事情。在這兩種情況下,將調用相同的函數,並且變量(自動或顯式定義將被分配)。唯一的區別是在第二種情況下,變量將準備好垃圾回收,而在第一種情況下,您需要等待超出範圍。

但是,當然第一個更可讀。

+0

-1有關GC的聲明不正確。實際上,直到方法退出才真正收集到任何東西。 (使用新的openJDK) – 2010-01-15 00:23:50

+0

是的,但在第一個版本中,變量s和i即使在方法退出後也不會被垃圾回收。將發生什麼取決於包裝代碼。 – kgiannakakis 2010-01-15 05:47:47

6

我寧願選擇第一個選項。然而,這與速度無關,但具有可調試性。在第二個選項中,我不能輕易檢查si的值。在性能方面,這根本不會有任何改變。

10

我高度懷疑這兩種形式是相同的,但不要拿我的這個詞。讓我們找出自己! :d

public class Tests { 

    public void test1() { 
     String s = methodThatReturnsString(); 
     int i = methodThatReturnsInt(); 
     thirdMethod(s, i); 
    } 

    public void test2() { 
     thirdMethod(methodThatReturnsString(), methodThatReturnsInt()); 
    } 

    public String methodThatReturnsString() { 
     return ""; 
    } 

    public int methodThatReturnsInt() { 
     return 0; 
    } 

    public void thirdMethod(String s, int i) { 

    } 

} 

讓我們編譯:

 
> javac -version 
javac 1.6.0_17 

> javac Tests.java 

現在,讓我們打印出來的字節碼指令!

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

public void test1(); 
    Code: 
    0: aload_0 
    1: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String; 
    4: astore_1 
    5: aload_0 
    6: invokevirtual #3; //Method methodThatReturnsInt:()I 
    9: istore_2 
    10: aload_0 
    11: aload_1 
    12: iload_2 
    13: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V 
    16: return 

public void test2(); 
    Code: 
    0: aload_0 
    1: aload_0 
    2: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String; 
    5: aload_0 
    6: invokevirtual #3; //Method methodThatReturnsInt:()I 
    9: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V 
    12: return 

public java.lang.String methodThatReturnsString(); 
    Code: 
    0: ldc  #5; //String 
    2: areturn 

public int methodThatReturnsInt(); 
    Code: 
    0: iconst_0 
    1: ireturn 

public void thirdMethod(java.lang.String, int); 
    Code: 
    0: return 

} 

我認爲這看起來有點奇怪 - test1()test2()不同。它看起來像編譯器正在添加調試符號。也許這是迫使它明確地分配返回值給局部變量,引入額外的指令。

讓我們嘗試用重新編譯沒有調試:

 
> javac -g:none Tests.java 
> javap -c Tests 
public class Tests extends java.lang.Object{ 
public Tests(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."":()V 
    4: return 

public void test1(); 
    Code: 
    0: aload_0 
    1: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String; 
    4: astore_1 
    5: aload_0 
    6: invokevirtual #3; //Method methodThatReturnsInt:()I 
    9: istore_2 
    10: aload_0 
    11: aload_1 
    12: iload_2 
    13: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V 
    16: return 

public void test2(); 
    Code: 
    0: aload_0 
    1: aload_0 
    2: invokevirtual #2; //Method methodThatReturnsString:()Ljava/lang/String; 
    5: aload_0 
    6: invokevirtual #3; //Method methodThatReturnsInt:()I 
    9: invokevirtual #4; //Method thirdMethod:(Ljava/lang/String;I)V 
    12: return 

public java.lang.String methodThatReturnsString(); 
    Code: 
    0: ldc  #5; //String 
    2: areturn 

public int methodThatReturnsInt(); 
    Code: 
    0: iconst_0 
    1: ireturn 

public void thirdMethod(java.lang.String, int); 
    Code: 
    0: return 

} 

不可思議!

因此,根據我的編譯器(Sun JDK),字節碼對於第二個版本而言較短。但是,虛擬機可能會優化任何差異。 :)

編輯:約阿希姆·紹爾的評論的一些額外的澄清禮貌:它是如何 實際執行上取決於很多:

需要注意的是字節 代碼告訴只是故事的一半是非常重要的 JVM(與 C/C++完全不同,在這裏你可以看到彙編程序 的代碼,它正是如何執行它的 )。我想你認識到, 但我認爲它應該在帖子中更明確 。

+2

需要注意的是,字節碼只告訴了一半:它的實際執行方式很大程度上取決於JVM(這與C/C++完全不同,在C/C++中,您可以看到彙編代碼以及它的執行方式)。我認爲你意識到這一點,但我認爲這個帖子應該更清楚。 – 2010-01-14 12:37:16

+0

@Joachim:我完全同意!我已將您的評論添加到答案中。 – 2010-01-14 12:47:13

+2

++花時間穿過它。我*沒有聽到的唯一的事情就是有人說,差異的相關性取決於函數內部的工作量。對於典型的功能,您發現的差異可能很容易產生噪音。 – 2010-01-14 14:32:59

0

實驗和測量。如果速度是關鍵,那麼測量速度。如果內存使用量很重要,請測量內存使用情況如果字節碼指令的數量非常重要,請對字節碼指令進行計數。如果代碼的可讀性是重要的,那麼測量代碼的可讀性。弄清楚如何衡量代碼的可讀性是你的功課。

如果你不試驗和測量所有你會得到的意見和論點。或者,如果你非常幸運,SO上的某個人會爲你運行你的實驗。

PS這篇文章當然是我的觀點和論點

相關問題