Câu hỏi liên quan

Máy ảo Java nhớ performace - mảng được viết nhanh hơn so với lần đọc Array?


0 Phiếu
Đã hỏi 04/5/2016 bởi OnceEve (1,740 điểm)
Tôi đã thực hiện một chuẩn mực ngắn trên một mảng dài trong java với kết quả khá lạ. Có vẻ như rằng đọc tuần tự với ngẫu nhiên viết nhanh hơn - một nửa thời gian - hơn các lần đọc ngẫu nhiên với thứ tự viết. Có bất cứ một đầu mối tại sao?? Dưới đây là hai phương pháp viết một loạt các một số longs (chạy với - Xmx2G, hay như vậy) ngẫu nhiên khi đọc tuần tự và đọc tuần tự khi viết bởi ngẫu nhiên:
import java.util.Random;

public class Scratch {
static Random random = new Random();
static long[] arr = new long[100000000];
static void seqReadRandWrite() {
    for(int i=0;i<arr.length;i++) {
        int at = random.nextInt(arr.length);
        arr[at] = arr[i];
    }
}
static void seqWriteRandRead() {
    for(int i=0;i<arr.length;i++) {
        int at = random.nextInt(arr.length);
        arr[i] = arr[at];
    }
}
public static void main(String[] args) throws Exception {
    seqWriteRandRead(); // warm up
    long nanos = System.nanoTime();
    seqReadRandWrite();
    System.out.println("Time: " + (System.nanoTime()-nanos) + "ns");
    nanos = System.nanoTime();
    seqWriteRandRead();
    System.out.println("Time: " + (System.nanoTime()-nanos) + "ns");
}
}
kết quả trên máy tính xách tay của tôi đang thời gian: 2774662168ns thời gian: 6059499068ns có nghĩa là nó hai lần càng nhanh để viết bởi ngẫu nhiên so với đọc... hay không? Là máy tính xách tay của tôi bị hỏng? PS.: điều này không yêu cầu bồi thường là một chuẩn mực, mặc dù hầu hết các điểm ở những lời khuyên liên kết về điểm chuẩn được bảo hiểm. Ngay cả khi tôi chạy đã 200, 000, 000 hoạt động nhiều lần, các resuts được khá thường xuyên. Có vẻ như (dường như!) di chuyển bộ nhớ từ các vị trí ngẫu nhiên vào tuần tự các khối là chậm hơn so với di chuyển bộ nhớ từ tuần tự các vị trí vào khối ngẫu nhiên ít với bộ nhớ của các kích thước này và cách ở trên để làm việc đó. và tôi tự hỏi tại sao?

4 Câu trả lời

0 Phiếu
Đã trả lời 19/5/2016 bởi navin (450 điểm)
được bình chọn là câu trả lời hay nhất 20/5/2016 bởi thisSboro
 
Câu trả lời hay nhất
Thử nghiệm của bạn bị hỏng, không phải là máy tính xách tay. Xem ở đây cho một cuộc thảo luận và một số công cụ để giúp đo hiệu suất: Java hiệu suất thời gian library dưới đây là một số kết quả hợp đồng của bạn. Cũng, tôi sửa đổi code của bạn phải cẩn thận trong cách nó cần đo đạc và khắt khe hơn.
Linux (Mint 14 mà là dựa trên Ubuntu 12.10) là môi trường tôi sử dụng Sun JDK 1.6.0_38 1.5G heap ví dụ lớn, ví dụ - Xmx1512
lưu ý: thú vị. Có thể là kết quả của tôi là khác nhau bởi vì kích thước của mảng là khác nhau dưới đây. Sẽ chạy lại và Cập Nhật. Nope: kết quả là tương tự như là không có nhiều sự khác biệt trong bình. Nhưng những gì thú vị là sự khác biệt so với ngắn chạy, tức là 21092.5 (/ 10 = 2109.2) vs 1645.2 có thể chậm hơn do bộ nhớ phân trang. kết quả với static long[] arr = new long[100000000]; (bản gốc kích thước mảng trong câu hỏi)
ghi: DescriptiveStatistics: n: 10 phút: 20893.0 tối đa: 22190.0 có nghĩa là: 21092.5 std dev: 390.90727800848117 trung bình: 20953.5 skewness: 3.0092198852491543 kurtosis: đọc 9.264808973899097: DescriptiveStatistics: n: 10 phút: 21668.0 tối đa: 22736.0 có nghĩa là: 21892.5 std dev: 318.31509546359877 trung bình: 21766.5 skewness: 2.5034216544466124 kurtosis: 6.560838306717343

tôi không nhìn thấy một sự khác biệt rất lớn trong đọc vs viết. Tôi đã thay đổi thử nghiệm để đo 10 lần trên một mảng nhỏ hơn một chút (kết quả là cùng một số lần đọc/viết). Vui lòng chạy lại với một kích thước mảng hoặc mẫu kích thước lớn hơn.
viết: DescriptiveStatistics: n: 10 phút: 1584.0 tối đa: 1799.0 có nghĩa là: 1645.2 std dev: 59.51619760853156 trung bình: 1634.5 skewness: 2.137918517 160 786 kurtosis: đọc 5.764166551997385: DescriptiveStatistics: n: 10 phút: 1568.0 tối đa: 2202.0 có nghĩa là: 1689.0 std dev: 186.93908693000031 trung bình: 1623.0 skewness: 2.770215113912315 kurtosis: 8.12245132320571
đây là một phiên bản chỉnh sửa của bạn code có nhiều mẫu:
import java.util.Random;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
public class Test {
    static Random random = new Random();
//  static long[] arr = new long[100000000];
    static long[] arr = new long[10000000];
    static void seqReadRandWrite() {
        for (int i = 0; i < arr.length; i++) {
            int at = Math.abs(random.nextInt()) % arr.length;
            arr[at] = arr[i];
        }
    }
    static void seqWriteRandRead() {
        for (int i = 0; i < arr.length; i++) {
            int at = Math.abs(random.nextInt()) % arr.length;
            arr[i] = arr[at];
        }
    }
    public static void main(String[] args) throws Exception {
        StopWatch timer = new StopWatch();
        int count = 10;
        // warm up
        for (int i=0; i<3; i++){
            seqReadRandWrite();
        }
        DescriptiveStatistics write = new DescriptiveStatistics();
        for (int i=0; i<count; i++){
            timer.reset();
            timer.start();
            seqReadRandWrite();
            timer.stop();
            write.addValue(timer.getTime());
        }
        System.out.println("Write: " + write);
        // warm up
        for (int i=0; i<3; i++){
            seqWriteRandRead(); 
        }
        DescriptiveStatistics read = new DescriptiveStatistics();
        for (int i=0; i<count; i++){
            timer.reset();
            timer.start();
            seqWriteRandRead();
            timer.stop();
            read.addValue(timer.getTime());
        }
        System.out.println("Read: " + read);

    }
}
Đã bình luận 20/5/2016 bởi thisSboro (180 điểm)
Tại sao bạn đã không khởi động method 'seqReadRandWrite ()' cũng? Bạn có chắc rằng một cuộc gọi duy nhất là đủ để gọi trình biên dịch JIT?
0 Phiếu
Đã trả lời 19/5/2016 bởi Vina_doesnt (240 điểm)
Tóm lại, các tiêu đề câu hỏi là một chút không chính xác. Sự thật có vẻ như được rằng trên mảng ngẫu nhiên một số môi trường (ví dụ như mỏ và của OP) viết nhanh hơn sau đó mảng ngẫu nhiên đọc . Nhưng lưu ý rằng đây không phải là true cho một số người khác. Dựa trên là bình luận tôi tách ra đọc và viết và thấy rằng ngẫu nhiên viết lần đọc nhanh hơn sau đó, ngẫu nhiên. Kết quả là như sau. Điều này có vẻ là lý do, và ý kiến tập thể ở đây dường như bỏ lỡ đọc vào bộ nhớ cache có đắt hơn sau đó bỏ lỡ ghi (nếu có bất kỳ bộ nhớ đệm tham gia vào việc viết ở tất cả). Trong sản xuất mặc dù nơi có hoạt động khác, điểm nóng có thể đóng một vai trò.
/cygdrive/c/Java/jdk1.7.0/bin/javac.exe Scratch.java && /cygdrive/c/Java/jdk1.7.0/bin/java Scratch
Starting
seqRead: 1273719725ns
seqRead: 1243055271ns
seqRead: 1245022497ns
seqRead: 1242868527ns
seqRead: 1241655611ns
randRead: 6900959912ns
randRead: 6965196004ns
randRead: 7379623094ns
randRead: 7020390995ns
randRead: 6938997617ns
seqWrite: 1266963940ns
seqWrite: 1250599487ns
seqWrite: 1246471685ns
seqWrite: 1230472648ns
seqWrite: 1246975416ns
randWrite: 3898382192ns
randWrite: 3897441137ns
randWrite: 3939947844ns
randWrite: 4207906037ns
randWrite: 4103594207ns
Compilation finished at Thu Jan 31 14:38:57
code sửa đổi của tôi là như sau:
import java.util.Random;

public class Scratch {
static Random random = new Random();
static long[] arr = new long[100000000];
static void seqReadRandWrite() {
    for(int i=0;i<arr.length;i++) {
        int at = Math.abs(random.nextInt() % arr.length);
        arr[at] = arr[i];
    }
}
static void seqWriteRandRead() {
    for(int i=0;i<arr.length;i++) {
        int at = Math.abs(random.nextInt() % arr.length);
        arr[i] = arr[at];
    }
}

static void seqRead() {
    int x = 0;
    for(int i=0;i<arr.length;i++) {
        int at = Math.abs(random.nextInt() % arr.length);
        x += arr[i];
    }
}
static void randRead() {
    int x = 0;
    for(int i=0;i<arr.length;i++) {
        int at = Math.abs(random.nextInt() % arr.length);
        x += arr[at];
    }
}
static void seqWrite() {
    for(int i=0;i<arr.length;i++) {
        int at = Math.abs(random.nextInt() % arr.length);
        arr[i] = at;
    }
}
static void randWrite() {
    for(int i=0;i<arr.length;i++) {
        int at = Math.abs(random.nextInt() % arr.length);
        arr[at] = at;
    }
}

public static void main(String[] args) throws Exception {
    // seqWriteRandRead(); // warm up
    System.out.println("Starting");
    long nanos =  -1;
    /*
    for (int i = 0; i < 5; i++) {       
        nanos = System.nanoTime();
        seqWriteRandRead();
        System.out.println("WriteRandRead Time: " + (System.nanoTime()-nanos) + "ns");
        nanos = System.nanoTime();
        seqReadRandWrite();
        System.out.println("ReadRandWrite Time: " + (System.nanoTime()-nanos) + "ns");
    }
    */
    for (int i = 0; i < 5; i++) {       
        nanos = System.nanoTime();
        seqRead();
        System.out.println("seqRead: " + (System.nanoTime()-nanos) + "ns");
    }
    for (int i = 0; i < 5; i++) {       
        nanos = System.nanoTime();
        randRead();
        System.out.println("randRead: " + (System.nanoTime()-nanos) + "ns");
    }

    for (int i = 0; i < 5; i++) {       
        nanos = System.nanoTime();
        seqWrite();
        System.out.println("seqWrite: " + (System.nanoTime()-nanos) + "ns");
    }
    for (int i = 0; i < 5; i++) {       
        nanos = System.nanoTime();
        randWrite();
        System.out.println("randWrite: " + (System.nanoTime()-nanos) + "ns");
    }
}
}
UPDATE đã cùng test trên Linux, với kết quả đáng kể khác nhau. Dưới đây, cột đầu tiên là các con số từ test của tôi và thứ hai là từ Tom's:
seqRead:   1273719725ns   2810487542ns  
seqRead:   1243055271ns   2780504580ns  
seqRead:   1245022497ns   2746663894ns  
seqRead:   1242868527ns   2746094469ns  
seqRead:   1241655611ns   2763107970ns  
randRead:  6900959912ns   23093543703ns 
randRead:  6965196004ns   22458781637ns 
randRead:  7379623094ns   24421031646ns 
randRead:  7020390995ns   25880250599ns 
randRead:  6938997617ns   26873823898ns 
seqWrite:  1266963940ns   4226886722ns  
seqWrite:  1250599487ns   4537680602ns  
seqWrite:  1246471685ns   3880372295ns  
seqWrite:  1230472648ns   4160499114ns  
seqWrite:  1246975416ns   4008607447ns  
randWrite: 3898382192ns   25985349107ns 
randWrite: 3897441137ns   22259835568ns 
randWrite: 3939947844ns   22556465742ns 
randWrite: 4207906037ns   22143959163ns 
randWrite: 4103594207ns   21737397817ns 
Đã bình luận 20/5/2016 bởi gurKy (110 điểm)
đó là chỉ cho bộ nhớ... Hãy thử nó, không có sự khác biệt
0 Phiếu
Đã trả lời 19/5/2016 bởi jur9974 (470 điểm)
Điểm chuẩn của bạn là sản xuất số điện thoại mà không kiểm tra "Họ có ý nghĩa?". Trong tình huống như vậy, bạn nên luôn luôn kiểm tra gấp đôi / ba / bốn phương pháp luận của bạn... BEFORE đối xử với các con số như là một sự phản ánh true về thực tế. Viết tiêu chuẩn đáng tin cậy là khó khăn. Và trong case Java, đặc biệt là khó khăn, bởi vì một số khía cạnh của các nền tảng Java có thể giới thiệu các biến dạng có hệ thống vào các phép đo điểm chuẩn của bạn... trừ khi bạn đặc biệt cho phép / bồi thường cho họ. Tuy nhiên, nguyên tắc "kiểm tra phương pháp của bạn" áp dụng để ALL thí nghiệm... đặc biệt là những người tạo ra kết quả không dường như làm cho tinh thần. (Như neutrino đi du lịch nhanh hơn ánh sáng...)
điều khác cần lưu ý là một khi bạn đã viết lại các điểm chuẩn vào tài khoản cho các yếu tố confounding, bạn có thể vẫn còn nhìn thấy con số bất ngờ. Vấn đề ở đây là rằng hiệu suất của các tiêu chuẩn như này có khả năng được nhạy cảm với những thứ như kích thước của L1 và L2 lưu trữ, kích thước bộ nhớ cache dòng, tốc độ tương đối của mức độ khác nhau của bộ nhớ... và của hổ tương tác dụng với trình hướng dẫn các chuẩn mực sản xuất trong vòng chặt chẽ, chính xác. Những việc này là phức tạp, khó khăn để phân tích, và có thể cung cấp cho counterintuitive hành vi. Và nó không phải là đáng ngạc nhiên (với tôi) mà máy khác nhau cho khác đo hiệu suất. Vì vậy, ngay cả khi các số liệu thực tế, nó vẫn là không an toàn để rút ra bất kỳ kết luận tổng quát về tốc độ của lần đọc so với viết từ chuẩn mực này. Thậm chí nếu bạn hạn chế chúng vào máy tính xách tay.
0 Phiếu
Đã trả lời 19/5/2016 bởi penna (500 điểm)
Điểm chuẩn của bạn là sản xuất số điện thoại mà không kiểm tra "Họ có ý nghĩa?". Trong tình huống như vậy, bạn nên luôn luôn tăng gấp đôi / ba / bốn kiểm tra phương pháp của bạn... BEFORE xử lý các con số như là một sự phản ánh true về thực tế. Viết tiêu chuẩn đáng tin cậy là khó khăn. Và trong case Java, đặc biệt là khó khăn, bởi vì một số khía cạnh của các nền tảng Java có thể giới thiệu các biến dạng có hệ thống vào các phép đo điểm chuẩn của bạn... trừ khi bạn đặc biệt cho phép / bồi thường cho họ. Tuy nhiên, nguyên tắc "kiểm tra phương pháp của bạn" áp dụng để ALL thí nghiệm... đặc biệt là những người tạo ra kết quả không dường như làm cho tinh thần. (Như neutrino đi du lịch nhanh hơn ánh sáng...)
điều khác cần lưu ý là một khi bạn đã viết lại các điểm chuẩn vào tài khoản cho các yếu tố confounding, bạn có thể vẫn còn nhìn thấy con số bất ngờ. Vấn đề ở đây là rằng hiệu suất của các tiêu chuẩn như này có khả năng được nhạy cảm với những thứ như kích thước của L1 và L2 lưu trữ, kích thước bộ nhớ cache dòng, tốc độ tương đối của mức độ khác nhau của bộ nhớ... và của hổ tương tác dụng với trình hướng dẫn các chuẩn mực sản xuất trong vòng chặt chẽ, chính xác. Những việc này là phức tạp, khó khăn để phân tích, và có thể cung cấp cho counterintuitive hành vi. Và nó không phải là đáng ngạc nhiên (với tôi) mà máy khác nhau cho khác đo hiệu suất. Vì vậy, ngay cả khi các số liệu thực tế, nó vẫn là không an toàn để rút ra bất kỳ kết luận tổng quát về tốc độ của lần đọc so với viết từ chuẩn mực này. Thậm chí nếu bạn hạn chế chúng vào máy tính xách tay.
Đã bình luận 21/5/2016 bởi Pbz_Sane (256,960 điểm)
Tôi gỡ bỏ ấm lên, chạy thử nghiệm cả hai trong vòng lặp, đảo ngược thứ tự. 'seqReadRandWrite' là một cách nhất quán khoảng hai lần như nhanh như 'seqWriteRandRead'.

ToughDev Q&A là gì?

Trang web hỏi đáp cho các bạn đam mê lập trình, phát triển phần mềm và các vấn đề kỹ thuật khác. Với sự giúp đỡ của bạn, chúng tôi hy vọng sẽ xây dựng thành công một thư viện đầy đủ các câu hỏi và trả lời về tất cả các vấn đề có liên quan đến lập trình!







...