2013-02-28 10 views
25

Trải nghiệm chung của tôi với Java 7 cho tôi biết rằng nó nhanh hơn Java 6. Tuy nhiên, tôi đã chạy vào đủ thông tin khiến tôi tin rằng đây không phải lúc nào cũng như vậy.Sự khác nhau giữa Java 6 và 7 có thể gây ra vấn đề về hiệu suất là gì?

Thông tin bit đầu tiên xuất phát từ dữ liệu Minecraft Snooper được tìm thấy here. Ý định của tôi là nhìn vào dữ liệu đó để xác định hiệu ứng của các công tắc khác nhau được sử dụng để khởi chạy Minecraft. Ví dụ tôi muốn biết nếu sử dụng -Xmx4096m có tác động tiêu cực hoặc tích cực đến hiệu suất. Trước khi tôi có thể đến đó, tôi đã xem xét phiên bản Java khác nhau đang được sử dụng. Nó bao gồm mọi thứ từ 1.5 đến một nhà phát triển sử dụng 1.8. Nói chung khi bạn tăng phiên bản java bạn thấy sự gia tăng hiệu suất fps. Trong suốt các phiên bản 1.6 khác nhau, bạn thậm chí còn thấy xu hướng tăng dần này. Tôi thành thật không mong đợi để xem như nhiều phiên bản khác nhau của java vẫn còn trong tự nhiên nhưng tôi đoán mọi người không chạy các bản cập nhật như họ cần.

Một số thời gian xung quanh các phiên bản sau này của 1.6 bạn sẽ có được những lần xem nhanh nhất. 1,7 thực hiện khoảng 10fps trung bình bên dưới các phiên bản sau 1.6 nhưng vẫn cao hơn các phiên bản 1.6. Trên một mẫu từ hệ thống của tôi, hầu như không thể thấy sự khác biệt nhưng khi nhìn vào mẫu rộng hơn thì rõ ràng.

Để kiểm soát khả năng ai đó có thể đã tìm thấy một công tắc ảo thuật cho Java tôi điều khiển bằng cách chỉ xem xét dữ liệu mà Không có công tắc nào được chuyển. Bằng cách đó tôi sẽ có một sự kiểm soát hợp lý trước khi tôi bắt đầu nhìn vào những lá cờ khác nhau.

Tôi đã loại bỏ hầu hết những gì tôi thấy vì đây có thể là một số Magic Java 6 mà ai đó không chia sẻ với tôi.

Bây giờ tôi đã làm việc trên một dự án khác yêu cầu tôi chuyển một mảng trong một InputStream để được xử lý bởi một API khác. Ban đầu tôi đã sử dụng một ByteArrayInputStream vì nó sẽ làm việc ra khỏi hộp. Khi tôi nhìn vào mã cho nó, tôi nhận thấy rằng mọi chức năng đều được đồng bộ hóa. Vì điều này là không cần thiết cho dự án này, tôi viết lại một với đồng bộ bị loại bỏ. Sau đó tôi quyết định rằng tôi muốn biết chi phí chung của Đồng bộ hóa là gì đối với tôi trong tình huống này.

Tôi đã thử một thử nghiệm đơn giản chỉ để xem. Tôi đã định thời gian mọi thứ với System.nanoTime() và sử dụng Java 1.6_20 x86 và 1.7.0-b147 AMD64, và 1.7_15 AMD64 và sử dụng máy chủ. Tôi dự kiến ​​phiên bản AMD64 sẽ hoạt động tốt hơn chỉ dựa trên kiến ​​trúc và có bất kỳ lợi thế nào của java 7. Tôi cũng nhìn vào phân vị 25, 50, và 75 (xanh dương, đỏ, xanh lục). Tuy nhiên 1.6 với máy chủ không có đánh bại quần tắt của mọi cấu hình khác. graph

Vì vậy, câu hỏi của tôi là. Có gì trong tùy chọn 1.6-máy chủ đang tác động đến hiệu suất cũng được mặc định ở trên 1,7?

Tôi biết hầu hết tăng cường tốc độ trong 1.7 đến từ việc mặc định một số tùy chọn hiệu suất cấp tiến hơn trong 1,6 ngày, nhưng một trong số đó gây ra sự khác biệt về hiệu suất. Tôi chỉ không biết cái nào để xem.

public class ByteInputStream extends InputStream { 

public static void main(String args[]) throws IOException { 
    String song = "This is the song that never ends"; 
    byte[] data = song.getBytes(); 
    byte[] read = new byte[data.length]; 
    ByteArrayInputStream bais = new ByteArrayInputStream(data); 
    ByteInputStream bis = new ByteInputStream(data); 

    long startTime, endTime; 

    for (int i = 0; i < 10; i++) { 
     /*code for ByteInputStream*/ 
     /* 
     startTime = System.nanoTime(); 
     for (int ctr = 0; ctr < 1000; ctr++) { 
      bis.mark(0); 
      bis.read(read); 
      bis.reset(); 
     } 
     endTime = System.nanoTime(); 

     System.out.println(endTime - startTime); 
     */ 

     /*code for ByteArrayInputStream*/ 
     startTime = System.nanoTime(); 
     for (int ctr = 0; ctr < 1000; ctr++) { 
      bais.mark(0); 
      bais.read(read); 
      bais.reset(); 
     } 
     endTime = System.nanoTime(); 

     System.out.println(endTime - startTime); 
    } 

} 

private final byte[] array; 
private int pos; 
private int min; 
private int max; 
private int mark; 

public ByteInputStream(byte[] array) { 
    this(array, 0, array.length); 
} 

public ByteInputStream(byte[] array, int offset, int length) { 
    min = offset; 
    max = offset + length; 
    this.array = array; 
    pos = offset; 
} 

@Override 
public int available() { 
    return max - pos; 
} 

@Override 
public boolean markSupported() { 
    return true; 
} 

@Override 
public void mark(int limit) { 
    mark = pos; 
} 

@Override 
public void reset() { 
    pos = mark; 
} 

@Override 
public long skip(long n) { 
    pos += n; 
    if (pos > max) { 
     pos = max; 
    } 
    return pos; 
} 

@Override 
public int read() throws IOException { 
    if (pos >= max) { 
     return -1; 
    } 
    return array[pos++] & 0xFF; 
} 

@Override 
public int read(byte b[], int off, int len) { 
    if (pos >= max) { 
     return -1; 
    } 
    if (pos + len > max) { 
     len = max - pos; 
    } 
    if (len <= 0) { 
     return 0; 
    } 
    System.arraycopy(array, pos, b, off, len); 
    pos += len; 
    return len; 
} 

@Override 
public void close() throws IOException { 
} 

}// end class 
+8

1 cho một đồ thị rất đẹp và câu hỏi cũng như các tài liệu. –

+9

Tôi có ý kiến ​​trái ngược. Có rất nhiều lời nói nhạo báng ở đây, và một biểu đồ đẹp, nhưng không có nội dung thực sự. Nếu bạn vừa mới hiển thị mã của mình và mô tả kết quả trong một bảng, nhiều người sẽ có thể giúp bạn. Vì nó là, tất cả các bạn có khả năng để có được dự đoán. -1 nếu tôi có thể. – parsifal

+0

Có gì trên trục Y? Bạn đã đo nhiều tác vụ lặp lại, không phải là một tác vụ đơn lẻ? Bạn có chắc chắn rằng GC không can thiệp vào kết quả không? – Dariusz

Trả lời

5

Tôi nghĩ rằng, như những người khác đang nói, rằng các xét nghiệm của bạn quá ngắn để xem vấn đề cốt lõi - đồ thị đang hiển thị nanoTime, và ngụ ý rằng phần lõi là Hoàn thành đo bằng 0,0001 đến 0.0006s.

Thảo luận

Sự khác biệt quan trọng trong -server và -Khách hàng là -server hy vọng JVM để được khoảng một thời gian dài và do đó expends nỗ lực sớm cho kết quả lâu dài tốt hơn.-những mục tiêu dành cho thời gian khởi động nhanh và hiệu suất đủ tốt.

Trong điểm phát sóng cụ thể chạy với nhiều tối ưu hóa hơn và các CPU này cần nhiều CPU hơn để thực thi. Nói cách khác, với máy chủ, bạn có thể thấy chi phí của trình tối ưu hóa vượt quá bất kỳ lợi ích nào từ việc tối ưu hóa.

Xem Real differences between "java -server" and "java -client"?

Ngoài ra, bạn cũng có thể được nhìn thấy những ảnh hưởng của tiered compilation ở đâu, trong Java 7, hotspot không kick vào quá nhanh. Chỉ với 1000 lần lặp lại, tối ưu hóa toàn bộ mã của bạn sẽ không được thực hiện cho đến sau này và do đó, lợi ích sẽ ít hơn.

Bạn có thể nhận được thông tin chi tiết nếu bạn chạy java với tùy chọn -Xprof JVM sẽ kết xuất một số dữ liệu về thời gian dành cho các phương thức khác nhau, cả được diễn giải và biên dịch. . Nó phải đưa ra một ý tưởng về những gì đã được biên soạn, và tỷ lệ (CPU) thời gian trước khi hotspot đá vào

Tuy nhiên, để có được một bức tranh trung thực, bạn thực sự cần phải chạy này nhiều còn - giây phút , không phải mili giây - để cho phép Java và hệ điều hành khởi động. Sẽ tốt hơn nếu lặp lại bài kiểm tra ở main (vì vậy bạn có một vòng lặp chứa vòng lặp thử nghiệm chính được thiết bị của bạn) để bạn có thể bỏ qua sự khởi động.

EDIT giây Đã đổi phút để đảm bảo hotspot đó, JVM và hệ điều hành là đúng 'ấm lên'

+0

và nếu bạn muốn đo một số hiệu suất thời gian chạy của một số ứng dụng cụ thể, thường là các ứng dụng chạy hàng giờ ... và các ứng dụng web chạy 24/7. Đôi khi nhấn mạnh với tải, đôi khi không. Đó là trường hợp sử dụng có liên quan, không phải trường hợp xảy ra trong mili giây đầu tiên hoặc giây. – eis

+0

@eis: Tôi nghe bạn. Ở đây, chúng ta có một phần rất nhỏ của mã để cấu hình (chứ không phải là một ứng dụng web) chỉ với một đường dẫn mã (không giống như bất kỳ mã thực) nào, và nó bị ràng buộc CPU (thay vì có bất kỳ hiệu ứng I/O nào) quá mức * trong trường hợp này *. Tôi hoàn toàn phù hợp với bạn trên quy mô mili giây. –