convert serializeKey' to strict ByteString

The builder produces a lazy ByteString, and L.toStrict has to copy it,
but needing to use the builder is no longer to common case; the
serialization will normally be cached already as a strict ByteString,
and this avoids keyFile' needing to use L.toStrict . serializeKey'
This commit is contained in:
Joey Hess 2019-01-14 16:59:27 -04:00
parent 4536c93bb2
commit e0c4ac99b5
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
5 changed files with 23 additions and 15 deletions

View file

@ -65,14 +65,14 @@ hashDirs (HashLevels 1) sz s = addTrailingPathSeparator $ take sz s
hashDirs _ sz s = addTrailingPathSeparator $ take sz s </> drop sz s hashDirs _ sz s = addTrailingPathSeparator $ take sz s </> drop sz s
hashDirLower :: HashLevels -> Hasher hashDirLower :: HashLevels -> Hasher
hashDirLower n k = hashDirs n 3 $ take 6 $ show $ md5 $ serializeKey' $ nonChunkKey k hashDirLower n k = hashDirs n 3 $ take 6 $ show $ md5s $ serializeKey' $ nonChunkKey k
{- This was originally using Data.Hash.MD5 from MissingH. This new version {- This was originally using Data.Hash.MD5 from MissingH. This new version
- is faster, but ugly as it has to replicate the 4 Word32's that produced. -} - is faster, but ugly as it has to replicate the 4 Word32's that produced. -}
hashDirMixed :: HashLevels -> Hasher hashDirMixed :: HashLevels -> Hasher
hashDirMixed n k = hashDirs n 2 $ take 4 $ concatMap display_32bits_as_dir $ hashDirMixed n k = hashDirs n 2 $ take 4 $ concatMap display_32bits_as_dir $
encodeWord32 $ map fromIntegral $ Data.ByteArray.unpack $ encodeWord32 $ map fromIntegral $ Data.ByteArray.unpack $
Utility.Hash.md5 $ serializeKey' $ nonChunkKey k Utility.Hash.md5s $ serializeKey' $ nonChunkKey k
where where
encodeWord32 (b1:b2:b3:b4:rest) = encodeWord32 (b1:b2:b3:b4:rest) =
(shiftL b4 24 .|. shiftL b3 16 .|. shiftL b2 8 .|. b1) (shiftL b4 24 .|. shiftL b3 16 .|. shiftL b2 8 .|. b1)

View file

@ -515,7 +515,7 @@ keyFile :: Key -> FilePath
keyFile = fromRawFilePath . keyFile' keyFile = fromRawFilePath . keyFile'
keyFile' :: Key -> RawFilePath keyFile' :: Key -> RawFilePath
keyFile' = S8.concatMap esc . L.toStrict . serializeKey' keyFile' = S8.concatMap esc . serializeKey'
where where
esc '&' = "&a" esc '&' = "&a"
esc '%' = "&s" esc '%' = "&s"

View file

@ -10,7 +10,7 @@ module Annex.VariantFile where
import Annex.Common import Annex.Common
import Utility.Hash import Utility.Hash
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString as S
variantMarker :: String variantMarker :: String
variantMarker = ".variant-" variantMarker = ".variant-"
@ -41,5 +41,5 @@ variantFile file key
where where
doubleconflict = variantMarker `isInfixOf` file doubleconflict = variantMarker `isInfixOf` file
shortHash :: L.ByteString -> String shortHash :: S.ByteString -> String
shortHash = take 4 . show . md5 shortHash = take 4 . show . md5s

21
Key.hs
View file

@ -56,11 +56,13 @@ stubKey = Key
-- Gets the parent of a chunk key. -- Gets the parent of a chunk key.
nonChunkKey :: Key -> Key nonChunkKey :: Key -> Key
nonChunkKey k = k nonChunkKey k
{ keyChunkSize = Nothing | keyChunkSize k == Nothing && keyChunkNum k == Nothing = k
, keyChunkNum = Nothing | otherwise = k
, keySerialization = Nothing { keyChunkSize = Nothing
} , keyChunkNum = Nothing
, keySerialization = Nothing
}
-- Where a chunk key is offset within its parent. -- Where a chunk key is offset within its parent.
chunkKeyOffset :: Key -> Maybe Integer chunkKeyOffset :: Key -> Maybe Integer
@ -96,12 +98,13 @@ buildKey k = byteString (formatKeyVariety (keyVariety k))
_ ?: Nothing = mempty _ ?: Nothing = mempty
serializeKey :: Key -> String serializeKey :: Key -> String
serializeKey = decodeBL' . serializeKey' serializeKey = decodeBS' . serializeKey'
serializeKey' :: Key -> L.ByteString serializeKey' :: Key -> S.ByteString
serializeKey' k = case keySerialization k of serializeKey' k = case keySerialization k of
Nothing -> toLazyByteStringWith (safeStrategy 128 smallChunkSize) L.empty (buildKey k) Nothing -> L.toStrict $
Just b -> L.fromStrict b toLazyByteStringWith (safeStrategy 128 smallChunkSize) L.empty (buildKey k)
Just b -> b
{- This is a strict parser for security reasons; a key {- This is a strict parser for security reasons; a key
- can contain only 4 fields, which all consist only of numbers. - can contain only 4 fields, which all consist only of numbers.

View file

@ -27,12 +27,14 @@ module Utility.Hash (
blake2b_512, blake2b_512,
#endif #endif
md5, md5,
md5s,
prop_hashes_stable, prop_hashes_stable,
Mac(..), Mac(..),
calcMac, calcMac,
prop_mac_stable, prop_mac_stable,
) where ) where
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy as L
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.Text.Encoding as T import qualified Data.Text.Encoding as T
@ -112,6 +114,9 @@ blake2b_512 = hashlazy
md5 :: L.ByteString -> Digest MD5 md5 :: L.ByteString -> Digest MD5
md5 = hashlazy md5 = hashlazy
md5s :: S.ByteString -> Digest MD5
md5s = hash
{- Check that all the hashes continue to hash the same. -} {- Check that all the hashes continue to hash the same. -}
prop_hashes_stable :: Bool prop_hashes_stable :: Bool
prop_hashes_stable = all (\(hasher, result) -> hasher foo == result) prop_hashes_stable = all (\(hasher, result) -> hasher foo == result)