Cách mô phỏng wc -l trong Raku


9

Trong perl 5, bạn có thể mô phỏng wc -lbằng oneliner:

perl -lnE 'END {say $.}' test.txt

Cách triển khai chức năng này trên Raku

Nếu bạn cố gắng thực hiện điều này:

raku -e 'say "test.txt".IO.open.lines.elems'

Hóa ra là chậm và sử dụng nhiều bộ nhớ

Thông tin để sao chép:

$ wget http://eforexcel.com/wp/wp-content/uploads/2017/07/1500000%20Sales%20Records.zip
$ unzip "1500000 Sales Records.zip"
$ mv "1500000 Sales Records.csv" part.txt
$ for i in `seq 1 10`; do cat part.txt >> test.txt ; done
$ du -sh test.txt
1.8G    test.txt

$ time wc -l test.txt
15000000 test.txt

real    0m0,350s
user    0m0,143s
sys     0m0,205s

$ time perl -lnE 'END { say $. }' test.txt
15000001

real    0m1,981s
user    0m1,719s
sys     0m0,256s

$ time raku -e 'say "test.txt".IO.open.lines.elems'
15000001

real    2m51,852s
user    0m25,129s
sys     0m6,378s

# Using swap (maximum uses 2.2G swap):
# Before `raku -e ''`

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          15009        1695       12604         107         708       12917
Swap:          7583           0        7583

# After `raku -e ''`

$ free -m
              total        used        free      shared  buff/cache   available
Mem:          15009         752       13923          72         332       13899
Swap:          7583         779        6804

# Swap not used
$ time raku -ne '++$ andthen END .say' test.txt
15000001

real    1m44,906s
user    2m14,165s
sys     0m0,653s

$ raku -v
This is Rakudo version 2019.11 built on MoarVM version 2019.11
implementing Perl 6.d.

3
Bạn có thể thêm thông tin về thời gian và đầu ra thực tế của wc(bao gồm kích thước tệp). Cảm ơn bạn.
Elizabeth Mattijsen

Cập nhật câu hỏi - ví dụ được thêm vào để sao chép
TheAthlete

2
@TheAthlete Cảm ơn bạn đã thêm thông tin. Tôi nghĩ rằng có khả năng đây sẽ là một [raku] SO thú vị trong lịch sử vì rakudo có thể đóng cửa ổn định khoảng cách hiệu suất trong những năm tới, vì vậy hãy xem xét thêm một vài thông tin. Đầu tiên, mặc dù rõ ràng bạn đang sử dụng một rakudo gần đây (vì bạn đang viết raku) nhưng vẫn có raku -vđầu ra tốt. Ngoài ra, vui lòng xem xét thêm đầu ra thời gian của đề xuất hiện tại của tôi. Ngoài ra, tôi có thể xem xét chuyển sang 'ascii'bộ giải mã vào cuối tuần này để tạo ra thời gian tốt hơn.
raiph

1
Một lưu ý phụ: -lcờ cho perl làm chậm đáng kể perl và nó không hữu ích trong trường hợp này. Trên máy của tôi cho một tệp có độ dài dòng ngẫu nhiên và khoảng 200 nghìn dòng, loại bỏ -lkết quả cải thiện 40%.
Sorin

Câu trả lời:


8

Một lựa chọn vẫn có thể khá chậm so với perlnhưng đáng để so sánh:

raku -ne '++$ andthen END .say' test.txt

Các ltùy chọn dòng lệnh là không cần thiết.

$ là một vô hướng nhà nước vô danh.

andthenkiểm tra xem lhs của nó được xác định và nếu vậy, đặt giá trị đó làm chủ đề ( $_) và sau đó đánh giá rhs của nó.

ENDtương tự như perlcủa END. Lưu ý rằng nó sẽ trả về Nilcho andthennhưng điều đó không quan trọng ở đây bởi vì chúng ta đang sử dụng ENDs tuyên bố' cho tác dụng phụ của nó.

Một số điều sẽ ảnh hưởng đến tốc độ của mã này. Một số điều tôi có thể nghĩ về:

  • Trình biên dịch khởi động trên không. Bỏ qua bất kỳ mô-đun nào đang được sử dụng, rakutrình biên dịch Rakudo có tổng phí khởi động khoảng một phần mười giây trên phần cứng thông thường so với một mô-đun khá không đáng kể cho perl.

  • Khái niệm về một "dòng". Trong đó perl, khái niệm mặc định về xử lý dòng là đọc một loạt byte, một số trong đó đại diện cho một đầu dòng. Trong đó raku, khái niệm mặc định về xử lý dòng là đọc chuỗi UTF-8, một số trong đó đại diện cho kết thúc dòng. Do đó, perlchỉ phát sinh chi phí đọc của bộ giải mã ASCII (hoặc ASCII mở rộng) trong khi rakuphát sinh chi phí đọc của bộ giải mã UTF-8.

  • Tối ưu hóa trình biên dịch. perlthường được tối ưu hóa đến mức tối đa. Nó sẽ không làm tôi ngạc nhiên nếu perl -lnE 'END {say $.}' test.txttận dụng một số tối ưu hóa thông minh. Ngược lại, công việc tối ưu hóa Rakudo vẫn còn khá sớm.

Điều duy nhất tôi nghĩ rằng bất cứ ai cũng có thể làm về điểm đầu tiên và cuối cùng trong ba điểm tôi đã đề cập ở trên là chờ đợi N năm và / hoặc đóng góp cho sự cải tiến của nhà soạn nhạc.

Sẽ có một cách để làm việc xung quanh UTF-8 theo mặc định của raku. Có lẽ một cái gì đó như sau đã có thể thực hiện được và nhanh hơn đáng kể so với mặc định của raku, ít nhất là bỏ qua chi phí sử dụng một mô-đun có tên foo:

raku -Mfoo -ne '++$ andthen END .say' test.txt

trong đó mô-đun foochuyển mã hóa mặc định cho tệp I / O sang ASCII hoặc bất cứ thứ gì từ các bảng mã có sẵn .

Tôi đã không kiểm tra rằng điều này thực sự có thể thực hiện được trong Rakudo hiện tại nhưng sẽ ngạc nhiên nếu không.

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.