cborg-json 0.2.1.0 → 0.2.2.0
raw patch · 4 files changed
+123/−13 lines, 4 filesdep +bytestringdep +cborg-jsondep +criteriondep ~aesondep ~basedep ~cborgPVP ok
version bump matches the API change (PVP)
Dependencies added: bytestring, cborg-json, criterion, deepseq, directory, process, zlib
Dependency ranges changed: aeson, base, cborg
API changes (from Hackage documentation)
Files
- ChangeLog.md +10/−1
- bench/Main.hs +67/−0
- cborg-json.cabal +30/−3
- src/Codec/CBOR/JSON.hs +16/−9
ChangeLog.md view
@@ -1,5 +1,14 @@ # Revision history for cborg-json -## 0.1.0.0 -- YYYY-mm-dd+## 0.2.2.0 -- 2019-12-29++* Use `replicateM` to significantly speed up decoding. Now faster than Aeson!++* Add support for decoding half-precision and single-precision floating-point+ numbers.++* Version bumps and support for GHC 8.8++## 0.1.0.0 -- 2017-08-01 * First version. Released on an unsuspecting world.
+ bench/Main.hs view
@@ -0,0 +1,67 @@+module Main (main) where++import qualified Data.ByteString.Lazy as LBS+import qualified Codec.Compression.GZip as GZip+import Control.Monad (unless)+import System.Directory (doesFileExist)+import System.Process (callProcess)++import Codec.CBOR.JSON (encodeValue, decodeValue)+import Codec.CBOR.Read (deserialiseFromBytes)+import Codec.CBOR.Write (toLazyByteString, toStrictByteString)++import Criterion.Main+ ( defaultMain, Benchmark, bgroup, bench, env, nf, whnf )+import qualified Data.Aeson as Aeson (Value, decode, encode)+++dataFile :: FilePath+dataFile = "bench/data.json.gz"++dataFileURL :: FilePath+dataFileURL = "https://raw.githubusercontent.com/well-typed/cborg/master/cborg-json/bench/data.json.gz"++fetchLargeJSON :: IO ()+fetchLargeJSON = do+ exists <- doesFileExist dataFile+ unless exists $ do+ putStrLn $ "Fetching bechmark data file from " ++ dataFileURL+ callProcess "curl" [dataFileURL, "--output", dataFile]++loadLargeJSONBytes :: IO LBS.ByteString+loadLargeJSONBytes = do+ fetchLargeJSON+ fmap GZip.decompress (LBS.readFile dataFile)++loadLargeJSON :: IO Aeson.Value+loadLargeJSON = do+ bytes <- loadLargeJSONBytes+ let Just json = Aeson.decode bytes+ return json++loadLargeCBORBytes :: IO LBS.ByteString+loadLargeCBORBytes =+ fmap (toLazyByteString . encodeValue) loadLargeJSON++main :: IO ()+main = defaultMain benchmarks++benchmarks :: [Benchmark]+benchmarks =+ [ bgroup "Decode"+ [ env loadLargeJSONBytes $ \largeJSONBytes ->+ bench "JSON" (whnf (Aeson.decode :: LBS.ByteString -> Maybe Aeson.Value) largeJSONBytes)++ , env loadLargeCBORBytes $ \largeCBORBytes ->+ bench "CBOR" (whnf (deserialiseFromBytes (decodeValue False)) largeCBORBytes)++ , env loadLargeCBORBytes $ \largeCBORBytes ->+ bench "CBOR lenient" (whnf (deserialiseFromBytes (decodeValue True)) largeCBORBytes)+ ]+ , env loadLargeJSON $ \largeJSON ->+ bgroup "Encode"+ [ bench "JSON" (nf Aeson.encode largeJSON)+ , bench "CBOR" (nf (toLazyByteString . encodeValue) largeJSON)+ , bench "CBOR strict" (whnf (toStrictByteString . encodeValue) largeJSON)+ ]+ ]
cborg-json.cabal view
@@ -1,5 +1,5 @@ name: cborg-json-version: 0.2.1.0+version: 0.2.2.0 synopsis: A library for encoding JSON as CBOR description: This package implements the bijection between JSON and CBOR defined in the CBOR specification, RFC 7049.@@ -16,12 +16,14 @@ build-type: Simple extra-source-files: ChangeLog.md cabal-version: >=1.10+tested-with:+ GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC==8.8.1 library exposed-modules: Codec.CBOR.JSON ghc-options: -Wall build-depends:- base >=4.7 && <4.13,+ base >=4.7 && < 4.14, aeson >=0.7 && <1.5, aeson-pretty >=0.8 && <0.9, unordered-containers >=0.2 && <0.3,@@ -33,4 +35,29 @@ default-language: Haskell2010 if impl(ghc >= 8.0)- ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances+ ghc-options: -Wcompat -Wnoncanonical-monad-instances++++benchmark bench+ type: exitcode-stdio-1.0+ hs-source-dirs: bench+ main-is: Main.hs++ default-language: Haskell2010+ ghc-options:+ -Wall -rtsopts -fno-cse -fno-ignore-asserts -fno-warn-orphans -O2++ other-modules:++ build-depends:+ base >= 4.6 && < 5.0,+ cborg ,+ cborg-json ,+ aeson ,+ bytestring >= 0.10.4 && < 0.11,+ criterion >= 1.0 && < 1.6,+ deepseq >= 1.0 && < 1.5,+ directory,+ process,+ zlib >= 0.5 && < 0.7
src/Codec/CBOR/JSON.hs view
@@ -7,7 +7,7 @@ import Data.Monoid import Control.Applicative-import Prelude+import Prelude hiding (decodeFloat) import Codec.CBOR.Encoding import Codec.CBOR.Decoding@@ -49,13 +49,15 @@ TypeNInt -> decodeNumberIntegral TypeNInt64 -> decodeNumberIntegral TypeInteger -> decodeNumberIntegral+ TypeFloat16 -> decodeNumberFloat16+ TypeFloat32 -> decodeNumberFloating TypeFloat64 -> decodeNumberFloating TypeBool -> Bool <$> decodeBool TypeNull -> Null <$ decodeNull TypeString -> String <$> decodeString - TypeListLen -> decodeListLen >>= flip (decodeListN lenient) []- TypeListLenIndef -> decodeListLenIndef >> (decodeListIndef lenient) []+ TypeListLen -> decodeListLen >>= decodeListN lenient+ TypeListLenIndef -> decodeListLenIndef >> decodeListIndef lenient [] TypeMapLen -> decodeMapLen >>= flip (decodeMapN lenient) HM.empty _ -> fail $ "unexpected CBOR token type for a JSON value: "@@ -67,12 +69,17 @@ decodeNumberFloating :: Decoder s Value decodeNumberFloating = Number . Scientific.fromFloatDigits <$> decodeDouble -decodeListN :: Bool -> Int -> [Value] -> Decoder s Value-decodeListN !lenient !n acc =- case n of- 0 -> return $! Array (V.fromList (reverse acc))- _ -> do !t <- decodeValue lenient- decodeListN lenient (n-1) (t : acc)+decodeNumberFloat16 :: Decoder s Value+decodeNumberFloat16 = do+ f <- decodeFloat+ if isNaN f || isInfinite f+ then return Null+ else return $ Number (Scientific.fromFloatDigits f)++decodeListN :: Bool -> Int -> Decoder s Value+decodeListN !lenient !n = do+ vec <- V.replicateM n (decodeValue lenient) + return $! Array vec decodeListIndef :: Bool -> [Value] -> Decoder s Value decodeListIndef !lenient acc = do