Câu hỏi Tại sao in “B” chậm hơn đáng kể so với in “#”?


Tôi tạo ra hai ma trận 1000 x 1000:

Ma trận đầu tiên: O và #.
Ma trận thứ hai: O và B.

Sử dụng đoạn mã sau, ma trận đầu tiên mất 8.52 giây để hoàn thành:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("#");
        }
    }

   System.out.println("");
 }

Với mã này, ma trận thứ hai mất 259.152 giây để hoàn thành:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("B"); //only line changed
        }
    }

    System.out.println("");
}

Lý do đằng sau những lần chạy khác nhau đáng kể là gì?


Như được đề xuất trong các ý kiến, chỉ in System.out.print("#"); lấy 7.8871 giây, trong khi System.out.print("B"); cho still printing....

Khi những người khác chỉ ra rằng nó hoạt động bình thường, tôi đã thử Ideone.com ví dụ, và cả hai đoạn mã thực hiện ở cùng một tốc độ.

Điều kiện thử nghiệm:

  • Tôi đã chạy thử nghiệm này từ Netbeans 7.2, với đầu ra vào giao diện điều khiển
  • Tôi đã sử dụng System.nanoTime() cho phép đo

2417
2018-02-21 23:45


gốc


Hãy thử thay đổi rand.nextInt (4) == 0 thành i <250 để loại bỏ hiệu ứng của bộ tạo ngẫu nhiên. Bạn có thể chạy ra khỏi entropy làm chậm các thế hệ ngẫu nhiên - fejese
Cả hai dường như chạy cùng một khoảng thời gian trên máy tính của tôi, ~ 4 giây. - Sotirios Delimanolis
nếu bạn đang cho rằng in ấn B mất nhiều thời gian hơn in ấn # .... tại sao bạn không thử in tất cả B & tất cả # thay vì dựa vào biến ngẫu nhiên r - Kakarot
Dựa trên câu trả lời được chấp nhận, bạn dường như không thử chạy nó với đầu ra được chuyển hướng đến một tệp hoặc / dev / null. - Barmar
@ fejese, Random () không phải là một mật mã rng và do đó không sử dụng lên các hồ bơi entropy. - Divide


Các câu trả lời:


Tinh khiết đầu cơ là bạn đang sử dụng thiết bị đầu cuối cố gắng thực hiện Gói từ chứ không phải là gói nhân vật và xử lý B như một nhân vật từ nhưng # như một nhân vật không phải từ. Vì vậy, khi nó đến cuối của một dòng và tìm kiếm một nơi để phá vỡ các dòng, nó thấy một # gần như ngay lập tức và vui vẻ phá vỡ ở đó; trong khi với B, nó phải tiếp tục tìm kiếm lâu hơn và có thể có nhiều văn bản hơn để bọc (có thể tốn kém trên một số thiết bị đầu cuối, ví dụ: xuất ra không gian, sau đó xuất các khoảng trống để ghi đè các chữ cái được bao bọc).

Nhưng đó là suy đoán thuần khiết.


3721
2018-04-03 15:01



Đây thực sự là câu trả lời đúng! Thêm dấu cách sau B giải quyết nó. - Kuba Spatny
Có một số câu trả lời đến từ kinh nghiệm học tập khó khăn. T.J. và tôi (kể từ khi chúng tôi là bạn) lớn lên trong những ngày của Apple] [và zx80 / ​​81. Không có từ được xây dựng trong bọc lại sau đó. Vì vậy, cả hai chúng tôi đã kết thúc bằng văn bản của riêng mình - hơn một lần. Và những bài học đó gắn bó với bạn, chúng bị đốt cháy trong bộ não thằn lằn của bạn. Nhưng nếu bạn dựa vào mã sau đó, khi từ môi trường của bạn kết thúc tốt đẹp mọi thứ, hoặc bạn làm điều đó theo cách thủ công trước khi chạy, khó có thể chạy vào các vấn đề với từ bọc. - JockM
Trích khấu trừ. Nhưng chúng ta nên khái quát từ bài học này, và luôn luôn đo lường hiệu suất với đầu ra hoặc loại bỏ, hướng đến / dev / null (NUL trên Windows) hoặc ít nhất là một tập tin. Hiển thị trên bất kỳ loại Bàn điều khiển nào nói chung là IO rất đắt tiền, và luôn luôn bóp méo thời gian - ngay cả khi không gây nhầm lẫn đáng kể như thế này. - Bob Kerns
@MrLister: System.out.println không làm wordwrapping; thứ mà nó xuất hiện là làm từ gói (và chặn, vì vậy System.out.println đã phải chờ đợi). - T.J. Crowder
@ Chris - thực sự, tôi sẽ tranh luận rằng không in chúng là giải pháp, cho vấn đề nhận được thời gian chính xác của thuật toán. Mỗi khi bạn in một Bảng điều khiển (của bất kỳ loại nào), bạn sẽ gọi tất cả các cách xử lý bên ngoài không liên quan đến những gì bạn đang thử nghiệm hiệu suất. Đó là một lỗi trong quy trình đo lường của bạn, tinh khiết và đơn giản. Mặt khác, nếu bạn xem vấn đề không phải là đo lường, nhưng hiểu sự khác biệt, sau đó có, không in ấn là một thủ thuật gỡ lỗi. Nó đi xuống, bạn đang cố giải quyết vấn đề gì? - Bob Kerns


Tôi đã thực hiện các bài kiểm tra trên Eclipse so với Netbeans 8.0.2, cả với phiên bản Java 1.8; Tôi đã sử dụng System.nanoTime() để đo lường.

Eclipse:

Tôi có cùng một lúc trên cả hai trường hợp - xung quanh 1.564 giây.

Netbeans:

  • Sử dụng "#": 1.536 giây
  • Sử dụng "B": 44.164 giây

Vì vậy, có vẻ như Netbeans có hiệu suất kém trên máy in để bàn điều khiển.

Sau nhiều nghiên cứu, tôi nhận ra rằng vấn đề là gói hàng của bộ đệm tối đa của Netbeans (nó không bị giới hạn trong System.out.println lệnh), được thể hiện bằng mã này:

for (int i = 0; i < 1000; i++) {
    long t1 = System.nanoTime();
    System.out.print("BBB......BBB"); \\<-contain 1000 "B"
    long t2 = System.nanoTime();
    System.out.println(t2-t1);
    System.out.println("");
}

Kết quả thời gian ít hơn 1 mili giây mỗi lần lặp trừ mỗi lần lặp thứ năm, khi kết quả thời gian là khoảng 225 mili giây. Một cái gì đó như (trong nano giây):

BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
.
.
.

Và cứ thế ..

Tóm lược:

  1. Eclipse hoạt động hoàn hảo với "B"
  2. Netbeans có một vấn đề dòng-line có thể được giải quyết (bởi vì vấn đề không xảy ra trong nhật thực) (mà không cần thêm không gian sau B ("B")).

148



bạn có thể xây dựng chiến lược nghiên cứu của bạn và sau đó điều cuối cùng đã dẫn bạn đến để tìm ra rằng dòng-gói là thủ phạm? (Tôi tò mò về kỹ năng thám tử của bạn, đó là!) - silph