Raku: có cách cực nhanh để biến một mảng thành một chuỗi mà không có khoảng cách ngăn cách các phần tử không?


8

Tôi cần chuyển đổi hàng ngàn chuỗi byte nhị phân, mỗi chuỗi dài khoảng một megabyte, thành chuỗi ASC. Đây là những gì tôi đã và đang làm, và dường như quá chậm:

sub fileToCorrectUTF8Str ($fileName) { # binary file
    my $finalString = "";
    my $fileBuf = slurp($fileName, :bin);    
    for @$fileBuf { $finalString = $finalString ~ $_.chr; };    
    return $finalString;
}

~ @ b biến @b thành chuỗi với tất cả các phần tử được phân tách bằng dấu cách, nhưng đây không phải là điều tôi muốn. Nếu @b = <abcd>; ~ @ b là "abc d"; nhưng tôi chỉ muốn "abcd", và tôi muốn làm điều này THỰC SỰ nhanh chóng.

Vì vậy, cách tốt nhất là gì? Tôi thực sự không thể sử dụng hyper cho song song vì chuỗi cuối cùng được xây dựng tuần tự. Hay tôi có thể?

Câu trả lời:


10

TL; DR Trên một rakudo cũ, .decodenhanh gấp khoảng 100 lần.

Ở dạng dài hơn để khớp với mã của bạn:

sub fileToCorrectUTF8Str ($fileName) { # binary file
  slurp($fileName, :bin).decode
}

Ghi chú hiệu suất

Đầu tiên, đây là những gì tôi đã viết để thử nghiệm:

# Create million and 1 bytes long file:
spurt 'foo', "1234\n6789\n" x 1e5 ~ 'Z', :bin;

# (`say` the last character to check work is done)
say .decode.substr(1e6) with slurp 'foo', :bin;

# fileToCorrectUTF8Str 'foo' );

say now - INIT now;

Trên rakudo của 2018.12TIO.run, phần trên .decodecó trọng lượng khoảng .05vài giây trên một triệu tệp thay vì khoảng 5giây cho giải pháp của bạn.

Tất nhiên, bạn có thể / nên thử nghiệm trên hệ thống của mình và / hoặc sử dụng các phiên bản rakudo sau này. Tôi hy vọng sự khác biệt sẽ vẫn theo cùng một thứ tự, nhưng trong thời gian tuyệt đối sẽ cải thiện rõ rệt khi năm tháng trôi qua. [1]

Tại sao nó nhanh gấp 100 lần?

Vâng, đầu tiên, @trên một Buf/ Blobmột cách rõ ràng lực lượng Raku để xem các xưa mục duy nhất ( một bộ đệm) như một số nhiều điều (một danh sách các yếu tố aka nhiều mục s ). Điều đó có nghĩa là phép lặp mức cao, đối với bộ đệm triệu phần tử, ngay lập tức là một triệu lần lặp / thao tác mức cao thay vì chỉ một thao tác mức cao.

Thứ hai, việc sử dụng .decodekhông chỉ tránh lặp mà còn phát sinh chi phí cuộc gọi phương thức tương đối chậm một lần trên mỗi tệp trong khi khi lặp lại có khả năng một triệu .chrcuộc gọi trên mỗi tệp. Các cuộc gọi phương thức (ít nhất là về mặt ngữ nghĩa) bị ràng buộc muộn , về nguyên tắc tương đối tốn kém so với, ví dụ, gọi một phụ thay vì một phương thức (phụ thường bị ràng buộc sớm ).

Tất cả đã nói:

  • Nhớ Caveat rỗng [1] . Ví dụ, các lớp tiêu chuẩn của rakudo tạo ra bộ đệm phương thức và dù sao thì trình biên dịch cũng hợp lý phương thức, vì vậy có thể có chi phí không đáng kể cho khía cạnh gọi phương thức.

  • Xem thêm trang Hiệu suất của tài liệu , đặc biệt là Sử dụng mã hiệu suất cao hiện có .

Là thông Buf.Strbáo lỗi LTA ?

Cập nhật Xem bình luận của Liz ++.

Nếu bạn cố gắng sử dụng .Strtrên một Bufhoặc Blob(hoặc tương đương, chẳng hạn như sử dụng ~tiền tố trên đó), bạn sẽ có một ngoại lệ. Hiện tại tin nhắn là:

Cannot use a Buf as a string, but you called the Str method on it

Các tài liệu cho .Strtrên a Buf/Blob hiện nói:

Để chuyển đổi thành Str bạn cần sử dụng .decode.

Có thể cho rằng LTA rằng thông báo lỗi không đề xuất điều tương tự.

Sau đó, một lần nữa, trước khi quyết định phải làm gì về vấn đề này, nếu có bất cứ điều gì, chúng ta cần xem xét những gì, và làm thế nào, dân gian có thể học hỏi từ bất cứ điều gì sai, bao gồm các tín hiệu về nó, chẳng hạn như thông báo lỗi, và cả những gì và cách họ làm trong thực tế hiện nay học hỏi, và thiên vị phản ứng của chúng tôi đối với việc xây dựng đúng văn hóa và cơ sở hạ tầng.

Đặc biệt, nếu dân gian có thể dễ dàng kết nối giữa một thông báo lỗi mà họ nhìn thấy và thảo luận trực tuyến xây dựng trên đó, thì cần phải tính đến và có lẽ được khuyến khích và / hoặc dễ dàng hơn.

Ví dụ: hiện tại SO này bao gồm vấn đề này với thông báo lỗi trong đó, vì vậy google có thể sẽ đưa ai đó đến đây. Dựa vào đó có thể là một con đường thích hợp hơn về phía trước hơn là thay đổi thông báo lỗi. Hoặc nó có thể không. Thay đổi sẽ dễ dàng ...

Vui lòng xem xét nhận xét bên dưới và / hoặc tìm kiếm các vấn đề rakudo hiện có để xem liệu cải thiện Buf.Strthông báo lỗi đang được xem xét và / hoặc liệu bạn có muốn mở một vấn đề để đề xuất thay đổi hay không. Mỗi tảng đá di chuyển ít nhất là tập thể dục tuyệt vời, và, khi nỗ lực tập thể của chúng ta ngày càng trở nên khôn ngoan, cải thiện (quan điểm của chúng ta) về ngọn núi .

Chú thích

[1] Như Caveat Empty nổi tiếng trong tiếng Latin nói , cả hiệu suất tuyệt đối và tương đối của bất kỳ tính năng raku cụ thể nào và nói chung là bất kỳ mã cụ thể nào, luôn chịu sự thay đổi do các yếu tố bao gồm khả năng của hệ thống, tải của nó trong suốt thời gian chạy mã và bất kỳ tối ưu hóa nào được thực hiện bởi trình biên dịch. Do đó, ví dụ, nếu hệ thống của bạn "trống", thì mã của bạn có thể chạy nhanh hơn. Hoặc, như một ví dụ khác, nếu bạn đợi một hoặc ba năm để trình biên dịch nhanh hơn, những tiến bộ trong hiệu suất của rakudo sẽ tiếp tục có triển vọng .



2
Có một vài cách bạn có thể tối ưu hóa hơn nữa điều này. slurpchỉ là một trình bao bọc IO::Path.slurptrong trường hợp này, vì vậy việc gọi .IO.slurpthay vào đó làm cho việc này nhanh hơn khoảng 2% trong điểm chuẩn của tôi. Nếu bạn nhét tệp vào :enc<latin1>, bạn sẽ có một bộ đệm ký tự giống như với mã hóa UTF-8 mặc định, nhưng bỏ qua các kiểm tra xem liệu tệp bị mờ có thực sự là UTF-8 hợp lệ mà bạn đang thực hiện khi giải mã không dù sao đến chuỗi UTF-8, điều này cũng giúp việc này nhanh hơn khoảng 10%.
Kaiepi

Cảm ơn mọi sự giúp đỡ của bạn !!! Với .decode và các thay đổi mã nhỏ khác, tôi tắt khoảng 8 giây cho mỗi chuỗi dài mà tôi phải xử lý. Cảm ơn !!!
lisprogtor

Hi @lisprogtor Ẩn dụ "cạo râu" có nghĩa là "giảm một số lượng rất nhỏ" . Thời gian của bạn trước khi giảm xuống còn khoảng 8 giây cho mỗi chuỗi dài là gì? Là giảm đủ?
raiph

8 giây chắc chắn tốt hơn "cạo râu"! Cảm ơn !!!
lisprogtor
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.