ประสิทธิภาพของsed
vs. tail
เพื่อลบบรรทัดแรกของไฟล์
TL; DR
sed
มีประสิทธิภาพและเอนกประสงค์ แต่นี่คือสิ่งที่ทำให้ช้าโดยเฉพาะอย่างยิ่งสำหรับไฟล์ขนาดใหญ่ที่มีหลายบรรทัด
tail
ทำสิ่งที่เรียบง่ายเพียงอย่างเดียว แต่สิ่งนั้นทำได้ดีและรวดเร็วแม้แต่ไฟล์ที่ใหญ่กว่าที่มีหลายบรรทัด
สำหรับไฟล์ขนาดเล็กและขนาดกลางsed
และtail
ทำงานอย่างรวดเร็วเช่นเดียวกัน (หรือช้าขึ้นอยู่กับความคาดหวังของคุณ) อย่างไรก็ตามสำหรับไฟล์อินพุตขนาดใหญ่ (หลาย MB) ความแตกต่างของประสิทธิภาพจะเพิ่มขึ้นอย่างมาก (ลำดับความสำคัญของไฟล์ในช่วงหลายร้อย MB) ด้วยtail
sed
ประสิทธิภาพสูงกว่าอย่างเห็นได้ชัด
การทดลอง
การเตรียมการทั่วไป:
คำสั่งของเราในการวิเคราะห์คือ:
sed '1d' testfile > /dev/null
tail -n +2 testfile > /dev/null
โปรดทราบว่าฉันกำลังส่งออกไปยังท่อ /dev/null
แต่ละครั้งเพื่อกำจัดเอาต์พุตเทอร์มินัลหรือการเขียนไฟล์เป็นคอขวดของประสิทธิภาพ
มาตั้งค่า RAM disk เพื่อกำจัด I / O disk ที่อาจเป็นปัญหาคอขวด ฉันมีการtmpfs
ติดตั้งส่วนตัวที่/tmp
ดังนั้นฉันก็แค่วางไว้ที่testfile
นั่นสำหรับการทดลองนี้
จากนั้นฉันก็สร้างไฟล์ทดสอบแบบสุ่มที่มีจำนวนบรรทัดที่ระบุ$numoflines
ด้วยความยาวบรรทัดแบบสุ่มและข้อมูลแบบสุ่มโดยใช้คำสั่งนี้ (โปรดทราบว่ามันไม่เหมาะสมอย่างแน่นอนมันช้ามาก ๆ ประมาณ> 2M บรรทัด แต่ใครสนใจมันไม่ใช่ สิ่งที่เรากำลังวิเคราะห์):
cat /dev/urandom | base64 -w0 | tr 'n' '\n'| head -n "$numoflines" > testfile
โอ้ววววว แล็ปท็อปทดสอบของฉันใช้งาน Ubuntu 16.04, 64 บิตบน Intel i5-6200U CPU เพียงเพื่อการเปรียบเทียบ
กำหนดเวลาไฟล์ขนาดใหญ่:
การตั้งค่าขนาดใหญ่testfile
:
การรันคำสั่งด้านบนด้วยการnumoflines=10000000
สร้างไฟล์สุ่มที่มีเส้น 10M ครอบครองบิตมากกว่า 600 MB - มันค่อนข้างใหญ่ แต่เรามาเริ่มด้วยเพราะเราสามารถ:
$ wc -l testfile
10000000 testfile
$ du -h testfile
611M testfile
$ head -n 3 testfile
qOWrzWppWJxx0e59o2uuvkrfjQbzos8Z0RWcCQPMGFPueRKqoy1mpgjHcSgtsRXLrZ8S4CU8w6O6pxkKa3JbJD7QNyiHb4o95TSKkdTBYs8uUOCRKPu6BbvG
NklpTCRzUgZK
O/lcQwmJXl1CGr5vQAbpM7TRNkx6XusYrO
แสดงการเรียกใช้ตามกำหนดเวลาด้วยขนาดใหญ่ของเราtestfile
:
ทีนี้ลองทำตามเวลาที่กำหนดด้วยคำสั่งทั้งคู่ก่อนเพื่อประเมินว่าเราทำงานขนาดใด
$ time sed '1d' testfile > /dev/null
real 0m2.104s
user 0m1.944s
sys 0m0.156s
$ time tail -n +2 testfile > /dev/null
real 0m0.181s
user 0m0.044s
sys 0m0.132s
เราได้เห็นผลชัดเจนจริงๆสำหรับไฟล์ขนาดใหญ่เป็นขนาดได้เร็วกว่าtail
sed
แต่เพื่อความสนุกและเพื่อให้แน่ใจว่าไม่มีผลข้างเคียงแบบสุ่มที่สร้างความแตกต่างอย่างมากลองทำ 100 ครั้ง:
$ time for i in {1..100}; do sed '1d' testfile > /dev/null; done
real 3m36.756s
user 3m19.756s
sys 0m15.792s
$ time for i in {1..100}; do tail -n +2 testfile > /dev/null; done
real 0m14.573s
user 0m1.876s
sys 0m12.420s
ข้อสรุปยังคงเหมือนเดิมsed
ไม่มีประสิทธิภาพในการลบบรรทัดแรกของไฟล์ขนาดใหญ่tail
ควรใช้ที่นั่น
และใช่ฉันรู้ว่าการสร้างลูปของ Bash ช้า แต่เราทำซ้ำได้ไม่กี่ครั้งที่นี่และเวลาที่ใช้ลูปธรรมดาไม่สำคัญเมื่อเทียบกับsed
/tail
runtimes
ไฟล์ขนาดเล็กเวลา:
การตั้งค่าขนาดเล็กtestfile
:
ตอนนี้เพื่อความสมบูรณ์ลองดูกรณีทั่วไปที่คุณมีไฟล์อินพุตขนาดเล็กในช่วง kB มาสร้างไฟล์อินพุตแบบสุ่มด้วยnumoflines=100
:
$ wc -l testfile
100 testfile
$ du -h testfile
8,0K testfile
$ head -n 3 testfile
tYMWxhi7GqV0DjWd
pemd0y3NgfBK4G4ho/
aItY/8crld2tZvsU5ly
ดำเนินการหมดเวลากับเราขนาดเล็ก testfile
:
เนื่องจากเราคาดว่าการกำหนดเวลาสำหรับไฟล์ขนาดเล็กดังกล่าวจะอยู่ในช่วงไม่กี่มิลลิวินาทีจากประสบการณ์เราจะทำ 1,000 การทำซ้ำทันที:
$ time for i in {1..1000}; do sed '1d' testfile > /dev/null; done
real 0m7.811s
user 0m0.412s
sys 0m7.020s
$ time for i in {1..1000}; do tail -n +2 testfile > /dev/null; done
real 0m7.485s
user 0m0.292s
sys 0m6.020s
อย่างที่คุณเห็นการจับเวลานั้นค่อนข้างคล้ายกันไม่มีอะไรมากที่จะตีความหรือสงสัย สำหรับไฟล์ขนาดเล็กเครื่องมือทั้งสองนั้นเหมาะสมอย่างเท่าเทียมกัน
sed
คือพกพาได้มากกว่า: "+2" สำหรับใช้tail
งานได้ดีบน Ubuntu ซึ่งใช้ GNUtail
แต่ไม่สามารถใช้กับ BSDtail
ได้