Учитывая, что этот пост влечет за собой:
- Haskell
- оптимизация кода
- показатели производительности
... можно с уверенностью сказать, что я нахожусь над моей головой. Тем не менее, я всегда чему-то учусь, когда захожу над головой, так что вот так.
Я начал изучать модули Data.ByteString.Lazy.*
Haskell через Hoogle и нашел функцию length для измерения длины ленивой ByteString. Это реализовано таким образом:
length :: ByteString -> Int64
length cs = foldlChunks (\n c -> n + fromIntegral (S.length c)) 0 cs
Хм. Джон действительно сказал, что "... сворачивание более 1021 * кусков файла в F # является основной частью того, почему это быстро ..." (мой акцент). И эта length
функция, по-видимому, также реализована с использованием короткого сгиба. Таким образом, похоже, что эта функция гораздо больше похожа на код «Яблоко», чем код Джона F #.
Имеет ли это значение на практике? Я сравнил пример Джона со следующим:
import System
import Data.List
import Data.ByteString.Lazy as B
main =
getArgs
>>= B.readFile . Data.List.head
>>= print . B.length
Пример Jon's Haskell на моей машине для файла объемом 1,2 ГБ: 10,5 с
Версия «коренастый»: 1.1s
«Коренастая» версия кода на Haskell почти в десять раз быстрее. Что говорит о том, что он, вероятно, в несколько раз быстрее, чем оптимизированный код F # Джона.
EDIT
Хотя я не обязательно полностью согласен с критикой Джоном моего примера, я хотел бы сделать его настолько безупречным, насколько это возможно. Таким образом, я профилировал следующий код:
import System
import Data.List
import Data.ByteString.Lazy as B
main =
getArgs
>>= B.readFile . Data.List.head
>>= print . B.count 0
Этот код загружает содержимое целевого файла в ByteString, а затем «подсчитывает» каждый случай появления байта с 0 значением. Если я что-то не упустил, эта программа должна загружать и оценивать каждый байт целевого файла.
Вышеуказанная программа работает примерно в 4 раза быстрее, чем последняя самая быстрая программа на Haskell, представленная Джоном, скопированная здесь для справки (в случае ее обновления):
import System
import Data.Int
import Data.List
import Data.ByteString.Lazy as B
main =
getArgs
>>= B.readFile . Data.List.head
>>= print . B.foldl (\n c -> n + 1) (0 :: Data.Int.Int64)