Недавно после запуска тестов в моем проекте я обнаружил, что прямое построение строгих байтов может быть на порядок быстрее, чем у строителя.
Например, реализация кодировщика, которая использует построитель:
encoder :: Int64 -> Data.ByteString.ByteString
encoder =
Data.ByteString.Lazy.toStrict .
Data.ByteString.Builder.toLazyByteString .
Data.ByteString.Builder.int64BE
выполняет в 10 раз хуже, чем тот, который напрямую строит байтовую строку и имеет несколько возможностей для дальнейшей оптимизации:
encoder :: Int64 -> Data.ByteString.ByteString
encoder =
unpackIntBySize 8
unpackIntBySize :: (Bits a, Integral a) => Int -> a -> Data.ByteString.ByteString
unpackIntBySize n x =
Data.ByteString.pack $ map f $ reverse [0..n - 1]
where
f s =
fromIntegral $ shiftR x (8 * s)
Итак, мой вопрос в два раза:
-
Почему нет прямого преобразования из
Builder
в строгийByteString
? Это раздражает, потому что мне часто приходится импортироватьData.ByteString.Lazy
только для использования его функцииtoStrict
, потому чтоData.ByteString.Builder
предоставляет толькоtoLazyByteString
. -
Указанный опыт, однако, заставило меня задуматься, если он не существует по какой-то причине. С той лишь разницей, что я применяю неверную схему использования в целом. Итак, действительно ли это неверно и есть лучшая альтернатива? Кстати, я знаю о
Data.ByteString.Builder.Prim
, но я сомневаюсь, что использование этого в случае, как указано выше, будет иметь большое значение.