Cara mengemulasi wc -l di Raku

9

Dalam perl 5, Anda dapat meniru wc -lmenggunakan oneliner:

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

Bagaimana menerapkan fungsi ini di Raku

Jika Anda mencoba menerapkan ini:

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

ternyata lambat dan menggunakan banyak memori

Informasi untuk direproduksi:

$ 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.
Atlet
sumber
3
Bisakah Anda menambahkan informasi waktu, dan output aktual wc(yang harus mencakup ukuran file). Terima kasih.
Elizabeth Mattijsen
Perbarui pertanyaan - contoh tambahan untuk reproduksi
TheAthlete
2
@TheAthlete Terima kasih atas info yang ditambahkan. Saya pikir kemungkinan ini akan menjadi [raku] yang secara historis menarik. Karena rakudo kemungkinan menutup kesenjangan kinerja selama beberapa tahun mendatang, maka silakan pertimbangkan untuk menambahkan beberapa info lebih lanjut. Pertama, meskipun jelas Anda menggunakan rakudo baru-baru ini (karena Anda sedang menulis raku) masih bagus untuk memiliki raku -vhasil. Juga, harap pertimbangkan untuk menambahkan output dari waktu saran saya saat ini. Juga, saya mungkin melihat beralih ke 'ascii'decoder akhir pekan ini untuk menghasilkan waktu yang lebih baik.
raiph
1
Di samping catatan: -lflag untuk perl memperlambat perl secara signifikan dan itu tidak berguna dalam kasus ini. Di komputer saya untuk file dengan panjang garis acak dan sekitar 200 ribu baris, menghapus -lhasil dalam peningkatan 40%.
Sorin

Jawaban:

8

Satu opsi yang kemungkinan masih sangat lambat dibandingkan perltetapi patut dibandingkan:

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

The lbaris perintah pilihan adalah berlebihan.

$ adalah skalar status anonim.

andthenmenguji apakah lhs didefinisikan, dan jika demikian, tetapkan nilai itu sebagai topik ( $_) dan kemudian mengevaluasi rhnya.

ENDmirip dengan perl's END. Perhatikan bahwa ia kembali Nilke andthentetapi tidak masalah di sini karena kami menggunakan pernyataan END's untuk efek sampingnya.

Beberapa hal akan memengaruhi kecepatan kode ini. Beberapa hal yang dapat saya pikirkan:

  • Kompilasi overhead startup. Mengabaikan modul apa pun yang digunakan, rakukompilator Rakudo memiliki overhead startup sekitar sepersepuluh detik pada perangkat keras tipikal dibandingkan dengan yang cukup dapat diabaikan perl.

  • Gagasan tentang "garis". Dalam perl, gagasan standar pemrosesan garis adalah membaca serangkaian byte, yang beberapa di antaranya mewakili akhir baris. Dalam raku, gagasan default pemrosesan baris adalah membaca string UTF-8, beberapa di antaranya mewakili akhir baris. Dengan demikian perlhanya menimbulkan overhead membaca dari decoder ASCII (atau Extended ASCII) sedangkan rakumenimbulkan overhead membaca dari decoder UTF-8.

  • Optimalisasi kompiler. perlumumnya dioptimalkan ke maks. Itu tidak akan mengejutkan saya jika perl -lnE 'END {say $.}' test.txtmengambil keuntungan dari beberapa optimasi pintar. Sebaliknya, pengoptimalan Rakudo masih dalam masa-masa awal.

Satu-satunya hal yang saya pikir bisa dilakukan oleh siapa pun tentang poin pertama dan terakhir dari tiga poin yang saya sebutkan di atas adalah menunggu selama N tahun dan / atau berkontribusi pada peningkatan kompiler.

Akan ada cara untuk mengatasi UTF-8-raku secara default. Mungkin sesuatu seperti yang berikut ini sudah bisa dilakukan dan secara signifikan lebih cepat daripada standar raku, setidaknya mengabaikan overhead menggunakan modul yang disebut foo:

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

di mana modul foomengalihkan pengodean default untuk file I / O ke ASCII atau apa pun dari pengkodean yang tersedia .

Saya belum memeriksa bahwa ini sebenarnya bisa dilakukan di Rakudo saat ini tetapi akan terkejut jika tidak.

raiph
sumber