Niedawno po uruchomieniu testów porównawczych w moim projekcie odkryłem, że bezpośrednia konstrukcja dokładnych próbek może być o rząd wielkości większa niż ta, w której uczestniczy konstruktor.Skuteczne tworzenie surowych ByteStrings
Np implementacja kodera, który wykorzystuje producentów:
encoder :: Int64 -> Data.ByteString.ByteString
encoder =
Data.ByteString.Lazy.toStrict .
Data.ByteString.Builder.toLazyByteString .
Data.ByteString.Builder.int64BE
zachowuje się jak 10 razy gorzej niż jednego, który konstruuje bytestring bezpośrednio i ma kilka możliwości dalszej optymalizacji:
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)
Więc moje pytanie jest dwojaki:
Wh y nie ma bezpośredniej konwersji z
Builder
do ścisłejByteString
? To denerwujące, ponieważ często muszę importowaćData.ByteString.Lazy
tylko po to, aby użyć jego funkcji , ponieważData.ByteString.Builder
ujawnia tylkotoLazyByteString
.Wspomniane doświadczenie sprawiło jednak, że zastanawiam się, czy nie jest to z jakiegoś powodu. Z tego powodu stosuję niepoprawny wzorzec użytkowania. Czy rzeczywiście jest to nieprawidłowe i czy istnieje lepsza alternatywa? BTW, wiem o
Data.ByteString.Builder.Prim
, ale wątpię, że użycie go w przypadku jak powyżej, miałoby duże znaczenie.
Interesujące. Do mojej codziennej pracy zakładam, że sposób budowania -> leniwy Bajtak -> ścisłe Bytestring opłaca się tylko przy budowaniu dużego ciągu z dużej liczby krótkich. Zwykle pakuję. pokaż do konwersji z liczb do ścisłych bs ... nie wiem, czy to dobrze. Czy mógłbyś opublikować kod, który może być użyty do mierzenia wydajności? To wygląda na ciekawy problem. – dsign
Istnieją dwie gałęzie projektu "postgresql-binary", które implementują enkodery za pomocą dwóch wspomnianych różnych strategii. Oba pochodzą z benchmarków wydajności kodowania. Oto [drzewo, w którym enkodery są zaimplementowane za pomocą bezpośredniej konstrukcji 'ByteString'] (https://github.com/nikita-volkov/postgresql-binary/tree/911a32110cfd618e2f7d377f4acc4c8f593f9acc), tutaj jest [ten obracający się wokół' Builder'] (https://github.com/nikita-volkov/postgresql-binary/tree/2fb6954968763621cbbdb8ba8505434ec2961b9e). –
Myślę, że problem polega na tym, że "Builder" nie utrzymuje liczby bajtów wymaganych do zapisania wynikowego testu, nawet jeśli nie robisz leniwego streamingu, jest to statycznie znane (O (1)) lub O (n) - ale prawdopodobnie warto. Możesz sprawdzić "builder-bufora" i sprawdzić, czy robi to, czego potrzebujesz. Zobacz dyskusję tutaj: https://github.com/chadaustin/buffer-builder/issues/7 – jberryman