2010-06-23 43 views
9

Tại sao phải mất quá nhiều thời gian để in một dòng mới? Đây có phải là máy của tôi, hoặc làm những người khác nhìn thấy cùng một hiệu ứng?Tại sao phải mất quá nhiều thời gian để in " n" trong Perl?

Với newline:

#!/usr/bin/perl 

use strict; 
use Benchmark; 

    timethis(100000,'main();'); 


    sub main { 
     print "you are the bomb. \n"; 
    } 


    # outputs: 
    # timethis 100000: 8 wallclock secs (0.15 usr + 0.45 sys = 0.60 CPU) @ 166666.67/s (n=100000) 

W/o newline:

#!/usr/bin/perl 

use strict; 
use Benchmark; 

    timethis(100000,'main();'); 


    sub main { 
     print "you are the bomb. "; 
    } 


    # outputs: 
    # timethis 100000: 0 wallclock secs (0.09 usr + 0.04 sys = 0.13 CPU) @ 769230.77/s (n=100000) 
    #  (warning: too few iterations for a reliable count) 

Edit: tôi muốn thêm rằng việc đặt hai "\ n" gây ra việc thực hiện để mất gấp hai lần, ít nhất là cho các giây xung quanh.

timethis 100000: 16 wallclock secs (0.15 usr + 0.52 sys = 0.67 CPU) @ 149253.73/s (n=100000) 
+0

bạn có đang chạy trên các cửa sổ không? Bạn có thể thử cùng một mã trên Linux hoặc mac? Theo kinh nghiệm của tôi, việc viết lên bàn điều khiển trên cửa sổ là một thủ tục rất chậm chạp, trong khi trên 2 cái kia của Big Three nó rất, rất nhanh. – rmeador

+0

@rmeador: Tôi đang chạy trên Linux. Tôi sẽ có thể làm thử nghiệm thêm một chút sau đó. Tôi không biết nếu điều này là bình thường cho newlines, hoặc nếu nó đã được b/c của các thiết lập (hệ điều hành, thiết bị đầu cuối, Perl, phần cứng, vv). – vol7ron

+0

như các câu trả lời đã nói, dòng mới luôn luôn chậm, tôi đã chỉ tự hỏi nếu bạn đã nhìn thấy một sự suy giảm hoàn toàn bất ngờ do Windows có hỗ trợ giao diện điều khiển lạ. – rmeador

Trả lời

12

Tôi không nghĩ rằng bộ đệm có nhiều việc phải làm với nó. Tôi đoán nó là bởi vì các thiết bị đầu cuối cần phải di chuyển khi bạn in một dòng mới cho nó (hoặc in đủ ký tự để điền vào một dòng). Khi tôi chuẩn các hàm này ghi vào một tệp hoặc tới /dev/null, không có nhiều khác biệt.

use Benchmark; 
timethis(1000000, 'main'); 
timethis(1000000, 'main2'); 
select STDERR; $| = 0; select STDOUT; # enable buffering on STDERR 
sub main { print STDERR "you are the bomb. \n" } 
sub main2 { print STDERR "you are the bomb. " } 

$ perl benchmark.pl 2> a_file 
timethis 1000000: 21 wallclock secs (4.67 usr + 13.38 sys = 18.05 CPU) @ 55410.87/s 
timethis 1000000: 21 wallclock secs (4.91 usr + 13.34 sys = 18.25 CPU) @ 54797.52/s 

$ perl benchmark.pl 2> /dev/null 
timethis 1000000: 26 wallclock secs (2.86 usr + 10.36 sys = 13.22 CPU) @ 75648.69/s 
timethis 1000000: 27 wallclock secs (2.86 usr + 10.30 sys = 13.16 CPU) @ 76010.95/s 

$ perl benchmark.pl 2> a_file  (without buffering) 
timethis 1000000: 29 wallclock secs (3.78 usr + 12.14 sys = 15.92 CPU) @ 62806.18/s 
timethis 1000000: 29 wallclock secs (3.27 usr + 12.51 sys = 15.78 CPU) @ 63367.34/s 

$ perl benchmark.pl 2> /dev/tty (window has 35 lines and buffers 10000, YMMV) 
[ 200000 declarations of how you are a bomb deleted ] 
timethis 100000: 53 wallclock secs (0.98 usr + 3.73 sys = 4.72 CPU) @ 21190.93/s 
timethis 100000: 9 wallclock secs (0.36 usr + 1.94 sys = 2.30 CPU) @ 43535.05/s 

Tóm tắt: thêm xả làm giảm hiệu suất khoảng 10%. Cuộn thêm trên thiết bị đầu cuối làm giảm hiệu suất khoảng 50%.

+0

Vậy điều đó có nghĩa là bất kỳ ngôn ngữ nào được viết cho bảng điều khiển sẽ có hiệu suất tương tự không? – justkt

+0

Tôi nghĩ đây có thể là câu trả lời đúng. Như được hiển thị bằng cách so sánh chỉnh sửa của tôi với ví dụ đầu tiên (hai dòng mới so với một), ngoài các giây xung nhịp, là thời gian thực tế, các giây CPU giống nhau. Tôi nghĩ rằng sự khác biệt chỉ có thể được suy ra cho một hoạt động đầu cuối, mà tôi chỉ có thể giả định sẽ được gây ra bởi di chuyển, hoặc bằng cách định vị lại con trỏ từ một dòng mới. – vol7ron

+0

@justkt, đó sẽ là một bổ sung tuyệt vời cho điểm chuẩn. Bạn có thể thử? :) – vol7ron

3

Newline flushes output.

Trong hầu hết các trường stdio, đệm khác nhau với các loại thiết bị đầu ra ... các thiết bị nối tiếp, bao gồm thiết bị đầu cuối, modem, chuột, và cần điều khiển, thường dòng đệm; stdio sẽ gửi toàn bộ dòng ra chỉ khi nó được xuống dòng

+0

Đầu ra là để các thiết bị đầu cuối và được xem như một trong hai: "bạn là bom bạn là bom ... bạn là bom timethis 100000..: Giây # wallclock ..." hoặc "bạn là bom. Bạn là bom. ... bạn là bom. Timethis 100000: # wallclock secs ..." Vì vậy, tất cả đầu ra được hiển thị trước dữ liệu điểm chuẩn. Việc xả nước vẫn có ảnh hưởng đến điều này? Tôi đã chỉ nhận thấy vấn đề với đỏ bừng, giống như ví dụ của bạn nói, nói chung trong kịch bản cgi. chỉnh sửa: nhận xét này không giữ định dạng, ví dụ 1 liệt kê đầu ra w/dòng mới, lần thứ 2 in chúng liên tiếp. – vol7ron

+0

Cảm ơn bạn đã bổ sung, nhưng nó cũng cho biết: "Chức năng in của Perl không hỗ trợ đầu ra không thực sự được tạo ra - một ghi vật lý cho từng ký tự riêng lẻ. " - Tôi mong đợi mọi việc thực thi Print sẽ thẳng đến đầu ra, không cần phải đệm. – vol7ron

8

Nó không phải là \n cho mỗi gia nhập gây ra vấn đề này. Thay vào đó, các cuộc gọi liên tiếp đến print được hệ điều hành đệm cho đến khi gặp phải ký tự \n hoặc bộ đệm đầy. Tại thời điểm đó, bộ đệm đầu ra được flushed vào màn hình. Việc làm sạch đầu ra cho màn hình là một hoạt động tốn kém (tương đối), vì vậy vòng lặp mà bạn xả bộ đệm đầu ra nhiều lần có hiệu suất chậm hơn nhiều so với vòng lặp mà bạn chỉ xóa bộ đệm một lần ở cuối (điều này sẽ xảy ra khi bạn thoát khỏi chương trình).

+1

Tôi cũng đã thử bật chức năng autoflush: "$ | ++;" trên dòng thứ hai. Điều này dường như không có hiệu lực. – vol7ron

Các vấn đề liên quan