Cách nhanh nhất để chạy một kịch bản là gì?


22

Tôi đã tự hỏi cách nhanh nhất để chạy tập lệnh là gì, tôi đã đọc được rằng có sự khác biệt về tốc độ giữa việc hiển thị đầu ra của tập lệnh trên thiết bị đầu cuối, chuyển hướng nó thành tập tin hoặc có lẽ /dev/null.

Vì vậy, nếu đầu ra không quan trọng, cách nhanh nhất để kịch bản hoạt động nhanh hơn, ngay cả khi nó là tối thiểu.

bash ./myscript.sh 
-or-
bash ./myscript.sh > myfile.log
-or-
bash ./myscript.sh > /dev/null


So sánh "chuyển hướng đến tệp thông thường" và "chuyển hướng đến / dev / null" có vẻ rất kỳ lạ đối với tôi ...
el.pescado

Câu trả lời:


31

Thiết bị đầu cuối ngày nay chậm hơn trước đây, chủ yếu là do card đồ họa không còn quan tâm đến khả năng tăng tốc 2D. Vì vậy, thực sự, in ra một thiết bị đầu cuối có thể làm chậm một tập lệnh, đặc biệt là khi cuộn có liên quan.

Do đó, ./script.shchậm hơn ./script.sh >script.log, do đó chậm hơn /script.sh >/dev/null, bởi vì sau này liên quan đến công việc ít hơn. Tuy nhiên, liệu điều này có đủ sự khác biệt cho bất kỳ mục đích thực tế nào hay không phụ thuộc vào mức độ đầu ra của tập lệnh của bạn và tốc độ. Nếu tập lệnh của bạn viết 3 dòng và thoát hoặc nếu nó in 3 trang mỗi vài giờ, có lẽ bạn không cần phải bận tâm với chuyển hướng.

Chỉnh sửa: Một số điểm chuẩn nhanh (và hoàn toàn bị phá vỡ):

  • Trong bảng điều khiển Linux, 240x75:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    3m52.053s
    user    0m0.617s
    sys     3m51.442s
  • Trong một xterm, 260x78:

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    0m1.367s
    user    0m0.507s
    sys     0m0.104s
  • Chuyển hướng đến một tệp, trên đĩa Samsung SSD 850 PRO 512GB:

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >file)
     real    0m0.532s
     user    0m0.464s
     sys     0m0.068s
  • Chuyển hướng đến /dev/null:

     $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done >/dev/null)
     real    0m0.448s
     user    0m0.432s
     sys     0m0.016s

6
@Kingofkech đó là ít hơn 200 dòng / giây. Nó sẽ không làm cho nhiều sự khác biệt. (Để so sánh, timeout 1 yes "This is a looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line"in hơn 100000 dòng trong một giây trên MBP của tôi.)
muru

4
@Kingofkech Nếu đây là tập lệnh thì hãy chỉnh sửa tệp và nhận xét dòng in ra đầu ra không cần thiết. Bạn sẽ kiếm được rất nhiều, đặc biệt nếu đây là một lệnh bên ngoài (không phải shell tích hợp) được thực thi 3 triệu lần ...
jimmij

2
Đối với một giải thích hẹp của "đã từng". Thiết bị đầu cuối vt220 chậm hơn so với trình giả lập thiết bị đầu cuối ngày nay. Ngoài ra, các máy trạm của SUN Sparc (những máy tôi đã sử dụng) có giao diện điều khiển rất chậm, vì vậy chỉ cần chuyển hướng đầu ra thành một tệp khi biên dịch một dự án lớn hơn sẽ tăng tốc thời gian biên dịch lên rất nhiều.
Kusalananda

1
@Kusalananda Đó là sự thật, xtermtrên HP Apollo từ 30 năm trước được sử dụng để thu thập thông tin so với xtermstrên HP-UX từ 20 năm trước. Tuy nhiên, bảng điều khiển Linux có thẻ video Matrox từ 15 năm trước chậm hơn so với bảng điều khiển Linux có thẻ S3 từ 20 năm trước. Và một giao diện điều khiển Linux với bộ đệm khung độ phân giải cao trên thẻ hiện đại đơn giản là không thể sử dụng được. :)
Satō Katsura

6
@Kingofkech Đó là khoảng 2400 bps. Một số người trong chúng ta thực sự sống nhiều năm với những tốc độ đó. :)
Satō Katsura

14

Tôi đã đồng ý theo bản năng với câu trả lời của Satō Katsura; nó có ý nghĩa Tuy nhiên, nó đủ dễ để kiểm tra.

Tôi đã thử viết một triệu dòng lên màn hình, viết (nối thêm) vào một tệp và chuyển hướng đến /dev/null. Tôi đã thử nghiệm lần lượt từng thứ một, sau đó thực hiện năm lần lặp lại. Đây là những lệnh tôi đã sử dụng.

$ time (for i in {1..1000000}; do echo foo; done)
$ time (for i in {1..1000000}; do echo foo; done > /tmp/file.log) 
$ time (for i in {1..1000000}; do echo foo; done > /dev/null)

Sau đó tôi vẽ tổng số lần dưới đây.

âm mưu thời gian so với đầu ra

Như bạn có thể thấy, những giả định của Satō Katsura là chính xác. Theo câu trả lời của Satō Katsura, tôi cũng nghi ngờ rằng yếu tố giới hạn sẽ là đầu ra, do đó, việc lựa chọn đầu ra sẽ có ảnh hưởng đáng kể đến tốc độ chung của kịch bản.

FWIW, câu trả lời ban đầu của tôi có mã khác, trong đó có tệp nối thêm và /dev/nullchuyển hướng bên trong vòng lặp.

$ rm /tmp/file.log; touch /tmp/file.log; time (for i in {1..1000000}; do echo foo >> /tmp/file.log; done) 
$ time (for i in {1..1000000}; do echo foo > /dev/null; done)

Như John Kugelman chỉ ra trong các bình luận, điều này thêm rất nhiều chi phí. Như câu hỏi đặt ra, đây không thực sự là cách đúng để kiểm tra nó, nhưng tôi sẽ để nó ở đây vì nó cho thấy rõ chi phí mở lại một tệp liên tục từ trong chính kịch bản.

âm mưu thời gian so với đầu ra

Trong trường hợp này, kết quả được đảo ngược.


FWIW Tôi đã thêm một điểm chuẩn nhanh vào câu trả lời của mình. Đáng chú ý, bảng điều khiển Linux chậm hơn 200 lần so với an xterm, lần lượt chậm hơn ~ 3 lần so với /dev/null.
Satō Katsura

Bạn cũng nên kiểm tra với một số giới hạn tỷ lệ. Sản lượng của OP là khoảng 200 dòng / s.
muru

@muru Ý bạn là in một dòng, đợi 1/200 giây, sau đó lặp lại? Tôi có thể thử, nhưng tôi cho rằng nó sẽ có kết quả tương tự, nhưng chỉ mất nhiều thời gian hơn để tín hiệu khắc phục nhiễu. Mặc dù có lẽ tôi có thể trừ đi thời gian chờ đợi trước khi phân tích.
Sparhawk

@Sparhawk một cái gì đó như thế. Tôi nghĩ rằng ở mức đầu ra đó, CPU sẽ có nhiều thời gian để cập nhật màn hình mà không làm chậm tốc độ đầu ra. Khi chương trình không làm gì ngoài việc phun các dòng mà không tạm dừng, bộ đệm đầu cuối sẽ được lấp đầy nhanh hơn màn hình có thể được cập nhật và tạo ra một nút cổ chai.
muru

3

Một cách khác để tăng tốc tập lệnh là sử dụng trình thông dịch shell nhanh hơn. So sánh tốc độ của vòng lặp bận POSIX , chạy theo bash v4.4 , ksh v93u + 20120801dash v0.5.8 .

  1. bash:

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | bash -s > /dev/null

    Đầu ra:

    real    0m25.146s
    user    0m24.814s
    sys 0m0.272s
  2. ksh:

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | ksh -s > /dev/null

    Đầu ra:

    real    0m11.767s
    user    0m11.615s
    sys 0m0.010s
  3. dash:

    time echo 'n=0;while [ $n -lt 1000000 ] ; do \
                      echo $((n*n*n*n*n*n*n)) ; n=$((n+1)); 
                   done' | dash -s > /dev/null

    Đầu ra:

    real    0m4.886s
    user    0m4.690s
    sys 0m0.184s

Một tập hợp con của các lệnh trong bashkshbackwardly tương thích với tất cả các lệnh trong dash. Một bashtập lệnh chỉ sử dụng các lệnh trong tập hợp con đó sẽ hoạt động với dash.

Một số bashtập lệnh sử dụng các tính năng mới có thể được chuyển đổi sang trình thông dịch khác. Nếu bashtập lệnh phụ thuộc nhiều vào các tính năng mới hơn, nó có thể không đáng bận tâm - một sốbash tính năng mới là các cải tiến vừa dễ viết mã hơn hiệu quả hơn, (mặc dù bashnói chung là chậm hơn), do đó dashtương đương, (có thể liên quan đến việc chạy Một số lệnh khác), sẽ chậm hơn.

Khi nghi ngờ, hãy chạy thử ...


Vì vậy, để nhanh chóng bash script của tôi, tôi cần phải viết lại chúng trong bash hoặc ksh?
Kingofkech

@Kingofkech Có thể là mã bạn đã viết cho bash dễ dàng sửa mã ksh hoặc mã dash. Cố gắng chỉ thay đổi người phiên dịch.
bli
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.