Làm thế nào là ksh93 nhanh như vậy?


9

Vì vậy, nói chung, tôi có xu hướng tìm cách sedxử lý văn bản - đặc biệt là đối với các tệp lớn - và thường tránh thực hiện các loại điều đó trong chính trình bao.

Tôi nghĩ, mặc dù, điều đó có thể thay đổi. Tôi đã chọc vào man kshvà tôi nhận thấy điều này:

<#pattern     Seeks forward to the beginning of the
              next line containing pattern.

<##pattern    The same as <# except that  the  por
              tion  of  the file that is skipped is
              copied to standard output.

Nghi ngờ về tính hữu dụng trong thế giới thực, tôi quyết định dùng thử. Tôi đã làm:

seq -s'foo bar
' 1000000 >file

... cho một triệu dòng dữ liệu trông giống như:

1foo bar
...
999999foo bar
1000000

... và đọ sức với nó sednhư:

p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"    
do </tmp/file eval "time ( $c )"
done | wc -l

Vì vậy, cả hai lệnh phải nhận được tối đa 999999foo và việc thực hiện khớp mẫu của chúng phải đánh giá ít nhất là bắt đầu và kết thúc của mỗi dòng để làm như vậy. Họ cũng phải xác minh char đầu tiên chống lại một mô hình phủ định. Đây là một điều đơn giản, nhưng ... Kết quả không như tôi mong đợi:

( sed '/^[^0-8]99999.*bar/q' ) \
    0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
    0.02s user 0.01s system 91% cpu 0.033 total
1999997

kshsử dụng ERE tại đây và sedBRE. Tôi đã làm điều tương tự với kshvà một mẫu vỏ trước đây nhưng kết quả không khác nhau.

Dù sao, đó là một sự khác biệt khá đáng kể - kshvượt trội hơn sed10 lần. Tôi đã đọc trước đó rằng David Korn đã viết io lib của riêng mình và thực hiện nó trong đó ksh- có thể điều này có liên quan? - nhưng tôi không biết gì về nó Làm thế nào là vỏ làm điều này rất tốt?

Điều tuyệt vời hơn nữa đối với tôi là nó kshthực sự để lại sự bù đắp ngay khi bạn hỏi nó. Để có được (gần như) giống với (GNU) sed bạn phải sử dụng -u- rất chậm .

Đây là một bài kiểm tra grepv.ksh

1000000         #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
    0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar   #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; )  \
    0.02s user 0.00s system 73% cpu 0.023 total

kshnhịp đập grepở đây - nhưng không phải lúc nào cũng vậy - chúng bị trói khá nhiều. Tuy nhiên, điều đó khá xuất sắc ksh cung cấp headđầu vào - bắt đầu trước khi trận đấu diễn ra.

Nó chỉ có vẻ quá tốt là đúng, tôi đoán. Những lệnh này làm khác nhau dưới mui xe là gì?

Ồ, và dường như thậm chí không có một subshell nào ở đây:

ksh -c 'printf %.5s "${<file;}"'

patternmột biểu thức chính quy hoặc một mẫu vỏ đơn giản hơn?
muru

@muru - Có thể là một trong hai, nhưng tôi không giỏi thay đổi những người xung quanh. Trong ví dụ đó là mẫu shell - mặc định.
mikeerv

@muru - Tôi đã thêm một w / một regex.
mikeerv

Câu trả lời:


8

Ksh không chỉ sử dụng sfio mà còn sử dụng bộ cấp phát bộ nhớ tùy chỉnh của riêng mình.

Tuy nhiên, dự đoán của tôi là sfio tạo ra sự khác biệt trong trường hợp này. Tôi vừa thử chạy ví dụ của bạn theo strace và có thể thấy rằng ksh gọi đọc / ghi ~ 200 lần (khối 65 KB) trong khi sed thực hiện ~ 3400 lần (khối 4 KB). Với sed -u máy tính xách tay của tôi gần như tan chảy, việc đọc được thực hiện trên mỗi byte và ghi trên mỗi dòng. Ksh đơn giản sử dụng lseek. Grep sử dụng đọc ~ 400 lần (khối 32 KB).


Vâng - không có bộ đệm không dành cho người yếu tim. Tôi tự hỏi nếu kshcông cụ regex của nó là hiệu quả như io của nó? Dù sao, cảm ơn rất nhiều cho câu trả lời. Tôi xin lỗi máy tính xách tay của bạn. Những gì về phân bổ bộ nhớ tùy chỉnh, mặc dù? Bạn có thêm gì về điều đó?
mikeerv

1
Thật đáng buồn không. Tất nhiên bạn có thể tải xuống mã nguồn từ trang web tại & t, nhưng đó là về nó. Thư viện được gọi là AST và chứa bộ cấp phát, công cụ regex và nhiều thứ khác. Vì vậy, hoàn toàn có thể là sự kết hợp của tất cả những điều đó làm cho ksh nhanh hơn nhiều.
Miroslav Franc


Cảm ơn bạn - điều này cũng có triển vọng: Một số thành phần có sẵn trong bộ sưu tập phần mềm AST là: Các lệnh POSIX Hầu hết các lệnh POSIX tiêu chuẩn đều có sẵn trong bộ sưu tập AST. Nhiều người được mã hóa dưới dạng các hàm thư viện có thể được thêm vào ksh dưới dạng lệnh tích hợp giúp cải thiện đáng kể hiệu năng. - Bây giờ tôi chỉ cần tìm ra cách xây dựng nó,
mikeerv 22/12/14

1
@mikeerv ksh có thể được xây dựng để sử dụng bộ phân bổ vmalloc của Phong Vo . Tạp chí có sẵn tại liên kết đó.
Đánh dấu Plotnick
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.