วิธีที่เร็วที่สุดในการเรียกใช้สคริปต์คืออะไร?


22

/dev/nullฉันถูกสงสัยว่าเป็นวิธีที่เร็วที่สุดที่จะเรียกใช้สคริปต์ที่ผมได้อ่านว่ามีความแตกต่างในความเร็วระหว่างการแสดงผลลัพธ์ของสคริปต์บนอาคารที่เปลี่ยนเส้นทางไปยังไฟล์หรือบางทีอาจจะ

ดังนั้นหากผลลัพธ์ไม่สำคัญวิธีที่เร็วที่สุดในการทำให้สคริปต์ทำงานเร็วขึ้นคืออะไรแม้ว่ามันจะน้อยก็ตาม

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


เปรียบเทียบ "เปลี่ยนเส้นทางไปยังแฟ้มปกติ" และ "เปลี่ยนเส้นทางไปยัง / dev / null" ดูเหมือนแปลกฉัน ...
el.pescado

คำตอบ:


31

เทอร์มินัลวันนี้ช้ากว่าที่เคยเป็นส่วนใหญ่เนื่องจากการ์ดกราฟิกไม่สนใจการเร่งความเร็วแบบ 2D อีกต่อไป ดังนั้นการพิมพ์ไปยังเทอร์มินัลอาจทำให้สคริปต์ช้าลงโดยเฉพาะเมื่อมีการเลื่อน

ดังนั้น./script.shจะช้ากว่า./script.sh >script.logซึ่งจะช้ากว่า/script.sh >/dev/nullเพราะหลังเกี่ยวข้องกับการทำงานน้อยลง อย่างไรก็ตามสิ่งนี้ทำให้เกิดความแตกต่างมากพอสำหรับการใช้งานจริงหรือไม่นั้นขึ้นอยู่กับว่าสคริปต์ของคุณสร้างออกมามากแค่ไหนและรวดเร็วแค่ไหน หากสคริปต์ของคุณเขียน 3 บรรทัดและออกหรือถ้าพิมพ์ 3 หน้าทุกสองสามชั่วโมงคุณอาจไม่ต้องกังวลกับการเปลี่ยนเส้นทาง

แก้ไข: มาตรฐานบางอย่าง (และเสียอย่างสมบูรณ์):

  • ในคอนโซล Linux, 240x75:

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

    $ time (for i in {1..100000}; do echo $i 01234567890123456789012345678901234567890123456789; done)
    real    0m1.367s
    user    0m0.507s
    sys     0m0.104s
  • เปลี่ยนเส้นทางไปยังไฟล์บนดิสก์ 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
  • เปลี่ยนเส้นทางไปที่/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 ที่น้อยกว่า 200 บรรทัด / วินาที มันจะไม่สร้างความแตกต่างมากนัก (สำหรับการเปรียบเทียบtimeout 1 yes "This is a looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line"พิมพ์ 100000 + เส้นในวินาทีเดียวบน MBP ของฉัน.)
Muru

4
@Kingofkech หากเป็นสคริปต์ให้แก้ไขไฟล์และใส่เครื่องหมายบรรทัดที่พิมพ์เอาท์พุทที่ไม่จำเป็นออก คุณจะได้รับมากโดยเฉพาะอย่างยิ่งถ้านี่เป็นคำสั่งภายนอก (ไม่ใช่เชลล์ในตัว) ดำเนินการ 3 ล้านครั้ง ...
jimmij

2
สำหรับการตีความที่แคบของ "เคยเป็น" เทอร์มินัล vt220 ช้ากว่าเครื่องจำลองเทอร์มินัลในปัจจุบัน นอกจากนี้เวิร์คสเตชั่น SUN Sparc (ที่ฉันใช้) มีคอนโซลที่ทำงานช้ามากดังนั้นเพียงแค่เปลี่ยนเส้นทางเอาต์พุตไปยังไฟล์เมื่อรวบรวมโครงการขนาดใหญ่
Kusalananda

1
@Kusalananda นั่นเป็นเรื่องจริงxtermบน HP Apollo เมื่อ 30 ปีก่อนเคยคลานเมื่อเทียบxtermsกับ HP-UX เมื่อ 20 ปีก่อน อย่างไรก็ตามคอนโซล Linux พร้อมการ์ดแสดงผล Matrox เมื่อ 15 ปีที่แล้วช้ากว่าคอนโซล Linux ตัวเดียวที่ใช้การ์ด S3 จาก 20 ปีก่อน และคอนโซล Linux ที่มีบัฟเฟอร์เฟรมความละเอียดสูงบนการ์ดที่ทันสมัยนั้นใช้ไม่ได้ :)
Satō Katsura

6
@ Kingofkech นั่นประมาณ 2,400 bps บางส่วนของเราอาศัยอยู่เป็นเวลาหลายปีด้วยความเร็วเหล่านั้น :)
Satō Katsura

14

ฉันจะเห็นด้วยกับคำตอบของSatō Katsura โดยสัญชาตญาณ มันทำให้รู้สึก อย่างไรก็ตามมันง่ายที่จะทดสอบ

ผมทดสอบการเขียนล้านเส้นไปยังหน้าจอการเขียน (ท้าย) /dev/nullเพื่อไฟล์และเปลี่ยนเส้นทางไปยัง ฉันทดสอบแต่ละอันแล้วก็ทำซ้ำห้าครั้ง นี่คือคำสั่งที่ฉันใช้

$ 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)

จากนั้นฉันก็พล็อตเวลาทั้งหมดด้านล่าง

พล็อตของเวลาเทียบกับผลลัพธ์

อย่างที่คุณเห็นข้อสันนิษฐานของSatō Katsura นั้นถูกต้อง ตามคำตอบของSatō Katsura ฉันยังสงสัยว่าปัจจัย จำกัด จะเป็นผลลัพธ์ดังนั้นจึงไม่น่าที่การเลือกผลลัพธ์จะมีผลอย่างมากต่อความเร็วโดยรวมของสคริปต์

FWIW คำตอบเดิมของฉันมีรหัสแตกต่างกันซึ่งมีไฟล์ต่อท้ายและ/dev/nullเปลี่ยนเส้นทางภายในลูป

$ 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)

เมื่อ John Kugelman ชี้ให้เห็นในความคิดเห็นสิ่งนี้จะเพิ่มค่าใช้จ่ายจำนวนมาก ตามที่คำถามยืนอยู่นี่ไม่ใช่วิธีที่ถูกต้องในการทดสอบจริง ๆ แต่ฉันจะทิ้งไว้ที่นี่เพราะมันแสดงให้เห็นถึงต้นทุนในการเปิดไฟล์ซ้ำ ๆ ซ้ำ ๆ จากภายในสคริปต์เอง

พล็อตของเวลาเทียบกับผลลัพธ์

ในกรณีนี้ผลลัพธ์จะกลับรายการ


FWIW ฉันเพิ่มเกณฑ์มาตรฐานอย่างรวดเร็วในคำตอบของฉัน ยวดลินุกซ์คอนโซล> 200 ครั้งช้ากว่าxtermซึ่งจะเป็น ~ 3 /dev/nullครั้งช้ากว่า
Satō Katsura

คุณควรทดสอบด้วยการ จำกัด อัตราบางอย่าง ผลลัพธ์ของ OP อยู่ที่ประมาณ 200 บรรทัด / วินาที
muru

@muru คุณหมายถึงการพิมพ์บรรทัดรอ 1/200 วินาทีจากนั้นทำซ้ำ? ฉันสามารถลองได้ แต่ฉันคิดว่ามันจะเป็นผลลัพธ์ที่คล้ายกัน แต่ใช้เวลานานกว่านี้ก่อนที่สัญญาณจะเอาชนะเสียงรบกวน แม้ว่าฉันจะลบเวลารอก่อนการวิเคราะห์ได้
Sparhawk

@Sparhawk บางอย่างเช่นนั้น ฉันคิดว่าที่ระดับเอาต์พุตนั้น CPU จะมีเวลามากมายในการอัพเดตจอแสดงผลโดยไม่ทำให้อัตราการส่งออกช้าลง เมื่อโปรแกรมไม่ทำอะไรเลยนอกจากพ่นเส้นโดยไม่มีการหยุดพักชั่วคราวเทอร์มินัลบัฟเฟอร์จะถูกเติมเต็มเร็วกว่าจอแสดงผลที่สามารถอัปเดตและสร้างคอขวดได้
muru

3

อีกวิธีในการเพิ่มความเร็วสคริปต์คือการใช้ตัวแปลเชลล์ที่เร็วขึ้น เปรียบเทียบความเร็วที่POSIXห่วงไม่ว่างทำงานภายใต้bash v4.4 , ksh v93u + 20120801และv0.5.8dash

  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

    เอาท์พุท:

    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

    เอาท์พุท:

    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

    เอาท์พุท:

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

เซตของคำสั่งในbashและkshมีbackwardly เข้ากันได้dashกับทุกคำสั่งใน สคริปต์ที่ใช้เพียงคำสั่งในกลุ่มย่อยที่ควรจะทำงานกับ bashdash

bashสคริปต์บางตัวที่ใช้คุณสมบัติใหม่สามารถแปลงเป็นล่ามอื่น หากbashสคริปต์อาศัยคุณลักษณะที่ใหม่กว่ามันอาจไม่คุ้มค่าเลย - คุณลักษณะใหม่บางอย่างbashเป็นการปรับปรุงที่ง่ายต่อการเขียนโค้ดและมีประสิทธิภาพมากขึ้น (แม้ว่าbashโดยทั่วไปแล้วจะช้ากว่า) ดังนั้นสิ่งที่dashเทียบเท่า อีกหลายคำสั่ง) จะช้าลง

เมื่อสงสัยให้ทำการทดสอบ ...


ดังนั้นเพื่อให้สคริปต์ bash ของฉันรวดเร็วฉันต้องเขียนมันใหม่ใน bash หรือ ksh?
Kingofkech

@ Kingofkech อาจเป็นไปได้ว่ารหัสที่คุณเขียนสำหรับ bash นั้นถูกต้อง ksh หรือรหัสรีบ พยายามเปลี่ยนล่าม
bli
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.