2011-05-11 33 views
23

Tôi đã thực hiện những nỗ lực khá kém trong vấn đề PRIME1 trên SPOJ. Tôi đã khám phá bằng cách sử dụng ByteString thực sự đã giúp hiệu suất cho việc đọc trong văn bản sự cố. Tuy nhiên, việc sử dụng ByteString để ghi lại kết quả thực sự hơi chậm hơn so với sử dụng các hàm Prelude. Tôi đang cố gắng tìm ra nếu tôi làm sai, hoặc nếu điều này được mong đợi.Khi nào tôi sử dụng ByteString và khi nào tôi không sử dụng?

tôi đã tiến hành lập hồ sơ và thời gian sử dụng (putStrLn.show) và ByteString tương đương ba cách khác nhau:

  1. tôi thử nghiệm mỗi ứng cử viên để xem nếu nó là số nguyên tố. Nếu vậy, tôi thêm nó vào danh sách và viết nó ra với (putStrLn. show)
  2. tôi thực hiện một danh sách của tất cả các số nguyên tố và viết ra danh sách sử dụng (. Unlines putStrLn. Show)
  3. tôi lập danh sách của tất cả các số nguyên tố và viết ra danh sách sử dụng bản đồ (putStrLn. chương trình)

tôi mong đợi con số 2 và 3 để thực hiện chậm hơn như bạn đang xây dựng một danh sách trong một chức năng và tiêu thụ nó trong khác. Bằng cách in các con số như tôi tạo ra chúng, tôi tránh phân bổ bất kỳ bộ nhớ cho danh sách. Mặt khác, bạn đang thực hiện cuộc gọi hệ thống gọi với mỗi cuộc gọi đến putStrLn. Đúng? Vì vậy, tôi đã thử nghiệm và # 1 trên thực tế là nhanh nhất.

Hiệu suất tốt nhất đạt được với tùy chọn # 1 và các hàm Prelude ([Char]). Tôi hy vọng rằng hiệu suất tốt nhất của tôi sẽ là tùy chọn # 1 với ByteString, nhưng đây không phải là trường hợp. Tôi chỉ sử dụng ByteStrings lười biếng, nhưng tôi không nghĩ rằng điều này sẽ quan trọng. Phải không?

Một số câu hỏi:

  • bạn mong chờ sự ByteStrings để thực hiện tốt hơn vì đã viết một loạt các Số nguyên stdout?
  • Tôi có thiếu mẫu cách để tạo và viết câu trả lời có thể dẫn đến hiệu suất tốt hơn ?
  • Nếu tôi chỉ viết ra các số là văn bản, khi nào, nếu, có bao giờ, có lợi ích khi sử dụng ByteString không?

Giả thuyết làm việc của tôi là viết ra Integer với ByteString chậm hơn bạn không kết hợp chúng với văn bản khác. Nếu bạn đang kết hợp Số nguyên với [Char], thì bạn sẽ có hiệu suất tốt hơn khi làm việc với ByteStrings. Nghĩa là, ByteString viết lại:

putStrLn $ "the answer is: " ++ (show value) 

sẽ nhanh hơn nhiều so với phiên bản được viết ở trên. Điều này có đúng không?

Cảm ơn bạn đã đọc!

Trả lời

18

Làm số lượng lớn đầu vào thường nhanh hơn với các dấu gạch ngang vì dữ liệu dày đặc, chỉ đơn giản là ít dữ liệu hơn để trộn từ đĩa vào bộ nhớ.

Ghi dữ liệu là đầu ra tuy nhiên, có một chút khác biệt.Thông thường, bạn đang tuần tự hóa một cấu trúc, tạo ra nhiều ghi nhỏ. Vì vậy, viết dày đặc, số lượng lớn của bytestrings không giúp bạn nhiều trong trường hợp đó. Thậm chí thường xuyên Strings sẽ hoạt động hợp lý ở đầu ra gia tăng.

Tuy nhiên, tất cả đều không bị mất. Chúng tôi có thể phục hồi số lượng lớn nhanh chóng viết bằng cách xây dựng hiệu quả bytestrings trong bộ nhớ. Cách tiếp cận này được thực hiện bởi các *-builder gói khác nhau:

Thay vì chuyển đổi các giá trị cho rất nhiều bytestrings nhỏ, và viết chúng ra cùng một lúc, chúng tôi dòng chuyển đổi vào một bộ đệm ngày càng phát triển, và đến lượt nó, viết bộ đệm đó thành một phần lớn. Điều này dẫn đến chi phí IO ít hơn rất nhiều, và cải tiến hiệu suất (thường là signficant) trên chuỗi IO.

Cách tiếp cận này được thực hiện bằng ví dụ: máy chủ web trong Haskell hoặc hệ thống HTML hiệu quả, blaze.

Ngoài ra, hiệu suất, ngay cả khi viết hàng loạt, sẽ phụ thuộc vào hiệu quả của bất kỳ chức năng chuyển đổi nào mà bạn có giữa các loại và bytestrings. Đối với Integer, bạn có thể chỉ cần sao chép mẫu bit trong bộ nhớ để xuất, hoặc thay vì đi qua một số bộ giải mã không hiệu quả. Kết quả là, đôi khi bạn phải suy nghĩ một chút về chất lượng của chức năng mã hóa bạn đang sử dụng, và không chỉ sử dụng Char/String hoặc bytestring IO.

+0

Bạn có thể chỉ cho tôi sự can đảm của một trong các thư viện được đề cập ở trên không. Tức là phần chuyển luồng chuyển đổi thành bộ đệm ngày càng phát triển? Tôi không quen thuộc với nội bộ của bất kỳ thư viện nào. Sẽ renderHtml trong Text.Blaze.Renderer.UTF8 là một ví dụ về điều này? –

+0

Ví dụ: trong binary a [builder] (http://hackage.haskell.org/packages/archive/binary/0.5.0.2/doc/html/src/Data-Binary-Builder.html#Builder) là một hàm liên tục cập nhật một bộ đệm có thể thay đổi, không đồng bộ. –

+0

Có vẻ như tôi có bài tập đọc buổi tối. Cảm ơn bạn! –

7

Lưu ý rằng hiệu suất không phải là sự khác biệt chính giữa ByteStringString. Trước đây là cho dữ liệu nhị phân trong khi sau đó là cho văn bản Unicode. Nếu bạn có dữ liệu nhị phân, hãy sử dụng ByteString, nếu bạn có văn bản Unicode, hãy sử dụng loại Text từ text package.

Các vấn đề liên quan