Hiệu suất sed
so với tail
để loại bỏ dòng đầu tiên của tệp
TL; DR
sed
là rất mạnh mẽ và linh hoạt, nhưng đây là những gì làm cho nó chậm, đặc biệt là đối với các tệp lớn có nhiều dòng.
tail
thực hiện chỉ một điều đơn giản, nhưng đó là một việc tốt và nhanh chóng, ngay cả đối với các tệp lớn hơn có nhiều dòng.
Đối với các tệp có kích thước vừa và nhỏ sed
và tail
đang thực hiện nhanh tương tự (hoặc chậm, tùy thuộc vào mong đợi của bạn). Tuy nhiên, đối với các tệp đầu vào lớn hơn (nhiều MB), sự khác biệt hiệu suất tăng đáng kể (một mức độ lớn cho các tệp trong phạm vi hàng trăm MB), với tail
hiệu suất vượt trội rõ ràng sed
.
Thí nghiệm
Chuẩn bị chung:
Các lệnh của chúng tôi để phân tích là:
sed '1d' testfile > /dev/null
tail -n +2 testfile > /dev/null
Lưu ý rằng tôi đang dẫn đầu ra cho /dev/null
mỗi lần để loại bỏ đầu ra đầu cuối hoặc tập tin ghi là nút cổ chai hiệu năng.
Chúng ta hãy thiết lập một đĩa RAM để loại bỏ I / O đĩa như một nút cổ chai tiềm năng. Cá nhân tôi đã tmpfs
gắn kết /tmp
vì vậy tôi chỉ cần đặt testfile
nó ở đó cho thí nghiệm này.
Sau đó, tôi đã từng tạo một tệp thử nghiệm ngẫu nhiên chứa một lượng dòng xác định $numoflines
với độ dài dòng ngẫu nhiên và dữ liệu ngẫu nhiên bằng lệnh này (lưu ý rằng nó chắc chắn không tối ưu, nó trở nên rất chậm đối với khoảng> 2M dòng, nhưng ai quan tâm, nó không phải là điều chúng tôi đang phân tích):
cat /dev/urandom | base64 -w0 | tr 'n' '\n'| head -n "$numoflines" > testfile
Ồ, btw. máy tính xách tay thử nghiệm của tôi đang chạy Ubuntu 16.04, 64 bit trên CPU Intel i5-6200U. Chỉ để so sánh.
Thời gian tập tin lớn:
Thiết lập rất lớn testfile
:
Chạy lệnh trên với numoflines=10000000
một tệp ngẫu nhiên chứa 10M dòng, chiếm hơn 600 MB - nó khá lớn, nhưng hãy bắt đầu với nó, bởi vì chúng ta có thể:
$ wc -l testfile
10000000 testfile
$ du -h testfile
611M testfile
$ head -n 3 testfile
qOWrzWppWJxx0e59o2uuvkrfjQbzos8Z0RWcCQPMGFPueRKqoy1mpgjHcSgtsRXLrZ8S4CU8w6O6pxkKa3JbJD7QNyiHb4o95TSKkdTBYs8uUOCRKPu6BbvG
NklpTCRzUgZK
O/lcQwmJXl1CGr5vQAbpM7TRNkx6XusYrO
Thực hiện chạy theo thời gian với số lượng lớn của chúng tôi testfile
:
Bây giờ chúng ta hãy thực hiện một lần chạy theo thời gian duy nhất với cả hai lệnh trước để ước tính mức độ chúng ta đang làm việc.
$ 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
Chúng tôi đã thấy một kết quả thực sự rõ ràng cho các tệp lớn, tail
nhanh hơn nhiều so với sed
. Nhưng chỉ để cho vui và để chắc chắn rằng không có tác dụng phụ ngẫu nhiên nào tạo ra sự khác biệt lớn, hãy làm điều đó 100 lần:
$ 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
Kết luận vẫn giữ nguyên, sed
không hiệu quả để loại bỏ dòng đầu tiên của một tệp lớn, tail
nên được sử dụng ở đó.
Và vâng, tôi biết các cấu trúc vòng lặp của Bash rất chậm, nhưng chúng tôi chỉ thực hiện tương đối ít lần lặp ở đây và thời gian một vòng lặp đơn giản không đáng kể so với sed
/ tail
thời gian chạy.
Thời gian tập tin nhỏ:
Thiết lập nhỏ testfile
:
Bây giờ để hoàn thiện, chúng ta hãy xem trường hợp phổ biến hơn là bạn có một tệp đầu vào nhỏ trong phạm vi kB. Hãy tạo một tệp đầu vào ngẫu nhiên với numoflines=100
, trông như thế này:
$ wc -l testfile
100 testfile
$ du -h testfile
8,0K testfile
$ head -n 3 testfile
tYMWxhi7GqV0DjWd
pemd0y3NgfBK4G4ho/
aItY/8crld2tZvsU5ly
Thực hiện chạy theo thời gian với nhỏ của chúng tôi testfile
:
Như chúng ta có thể mong đợi thời gian cho các tệp nhỏ như vậy nằm trong phạm vi vài mili giây từ kinh nghiệm, hãy thực hiện ngay 1000 lần lặp:
$ 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
Như bạn có thể thấy, thời gian khá giống nhau, không có nhiều điều để diễn giải hay thắc mắc. Đối với các tệp nhỏ, cả hai công cụ đều phù hợp như nhau.
sed
tính di động cao hơn: "+2" đểtail
hoạt động tốt trên Ubuntu, sử dụng GNUtail
, nhưng sẽ không hoạt động trên BSDtail
.