2015-10-18 26 views
12

Son zamanlarda sıkı bytestrings doğrudan inşaat hızlı bir inşaatçı karıştığı olandan büyüklükte bir sipariş olabileceğini keşfettim benim proje üzerinde kriterler çalıştırdıktan sonra sıkı ByteStrings yaratır.Verimli

bir inşaatçı kullanan Örneğin, bir kodlayıcı uygulaması:

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) 
: Doğrudan bytestring oluşturur ve daha fazla optimizasyon için farklı olasılıklar vardır biri daha kötü 10 kez gibi

encoder :: Int64 -> Data.ByteString.ByteString 
encoder = 
    Data.ByteString.Lazy.toStrict . 
    Data.ByteString.Builder.toLazyByteString . 
    Data.ByteString.Builder.int64BE 

gerçekleştirdiği

benim soru iki yönlüdür:

  1. Wh y Builder'dan ByteString numaralı telefona doğrudan dönüşüm yok mu? Sık sık sadece kendi toStrict işlevini kullanmak Data.ByteString.Lazy ithal etmek zorunda çünkü Data.ByteString.Builder sadece toLazyByteString ortaya çıkarır, çünkü, sinir bozucu.

  2. belirtilen deneyim ancak bunun bir sebebi yoksa o anda bana, merak yaptı. Nedeni ile tamamen yanlış kullanım modelini uygulamam. Yani, gerçekten yanlış mı ve daha iyi bir alternatif var mı? BTW, ben Data.ByteString.Builder.Prim hakkında biliyorum, ama yukarıdaki gibi bir durumda kullanmak, çok fark yaratacağından şüpheliyim.

+0

İlginç. Günlük çalışmam için yapımcı -> tembel ByteString -> sıkı Bytestring'in sadece çok sayıda kısa diziden büyük bir dizge oluştururken ödediğini varsayıyorum. Ben genelde paketlerim. Sayılardan katı bs'ye dönüştürmek için göster ... iyi olup olmadığını bilmiyorum. Performansı ölçmek için kullanılabilecek bir kod gönderebilir misiniz? Bu ilginç bir konuya benziyor. – dsign

+0

Kodlayıcıları belirtilen iki farklı stratejiyi kullanarak uygulayan "postgresql-binary" projesinin iki dalı vardır. Her ikisi de kodlama performansı kriterleriyle gelir. İşte burada [kodlayıcıların doğrudan 'ByteString' inşası kullanılarak uygulandığı bir ağaç] (https://github.com/nikita-volkov/postgresql-binary/tree/911a32110cfd618e2f7d377f4acc4c8f593f9acc), işte burada [Builder'ın etrafında dönen] (https://github.com/nikita-volkov/postgresql-binary/tree/2fb6954968763621cbbdb8ba8505434ec2961b9e). –

+1

Zahmet Builder' yazmak için gerekli bayt sayısı tutmaz 'olduğunu düşünüyorum sonuçlanan rağmen dışarı bytestring bu ya statik olarak bilinen (O (1)) veya O (tembel akışı yapmıyoruz zaman n) but-muhtemelen-değer-it. Arabellek oluşturucuyu kontrol edebilir ve ihtiyacınız olanı yaptırabilirsin. Burada tartışmaya bakın: https://github.com/chadaustin/buffer-builder/issues/7 – jberryman

cevap

7

Oluşturucu sıfır maliyetli bir soyutlama değildir, büyük tembel dizeler için optimize edilmiştir. oluşturucu docs Gönderen:

şu anki uygulama Senin durumunda 4kB ve 32 KB

arasında bir ortalama yığın boyutu için ayarlanmıştır, oluşturucu sadece 8 bayt üretmek için bütün 4k yığını ayırır.

gerekli tampon boyutunu hesaplar olarak dağıtır pack ile karşılaştır ve daha sonra bir döngü içinde doldurur. Verimsizliğin tek kaynağı, önceden ayrılmış olan 8 Word8 listesidir. Muhtemelen unfoldrN daha da verimli olacaktır.

Kük sıkı tirnaklar oluşturmak için oluşturucu kullanmak bazen uygundur, ancak daha iyi yollar vardır.

+0

Teşekkürler! "Daha iyi yollardan" bahsediyorsun. Ne ima ediyorsun? Önereceğin kütüphaneler var mı? –

+0

@NikitaVolkov Ben 'unfoldrN' gibi ad hoc bir şekilde performans için daha iyi anlamına gelir. Hayatı kolaylaştıran özel bir kitaplık bilmiyorum ve genellikle performans kritik olmadığında test üreticisi tarafından kullanıyorum. – Yuras

+0

Küçük, sıkı bytestringleri birleştirmeye ne dersiniz? Sadece "append" ve/veya "concat" kullanmanın en verimli yolu nedir? –

3

ByteString yapιşιnι ayarlamak için Data.ByteString.Builder.Extra adresinden toLazyByteStringWith kullanmayı deneyin. Bu, arabellek boyutunu ve büyüme oranını ayarlamanıza olanak veren bir AllocationStrategy alır.