salak 0.3.5.1 → 0.3.5.2
raw patch · 10 files changed
+185/−62 lines, 10 filesdep ~data-defaultdep ~scientificdep ~time
Dependency ranges changed: data-default, scientific, time, unordered-containers
Files
- README.md +95/−0
- bench/SalakBench.hs +7/−1
- salak.cabal +7/−41
- src/Salak/Internal.hs +8/−2
- src/Salak/Internal/Prop.hs +4/−3
- src/Salak/Internal/Source.hs +2/−2
- test/Salak/Internal/KeySpec.hs +3/−3
- test/Salak/Internal/PropSpec.hs +14/−2
- test/Salak/Internal/SourceSpec.hs +44/−7
- test/Salak/TrieSpec.hs +1/−1
README.md view
@@ -47,6 +47,101 @@ Environment: PACKAGE_A_ENABLED: false ``` +## Performance++#### Load Performance++```log+benchmarking load/loadMock+time 12.91 μs (12.86 μs .. 12.95 μs)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 12.95 μs (12.90 μs .. 13.02 μs)+std dev 200.7 ns (150.4 ns .. 267.6 ns)+variance introduced by outliers: 12% (moderately inflated)++benchmarking load/loadCMD+time 666.5 ns (665.6 ns .. 667.8 ns)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 668.8 ns (666.7 ns .. 672.7 ns)+std dev 9.395 ns (5.114 ns .. 14.75 ns)+variance introduced by outliers: 13% (moderately inflated)++benchmarking load/loadEnv+time 1.823 ms (1.813 ms .. 1.833 ms)+ 1.000 R² (0.999 R² .. 1.000 R²)+mean 1.803 ms (1.791 ms .. 1.814 ms)+std dev 39.13 μs (31.88 μs .. 48.43 μs)++benchmarking load/loadYaml+time 116.9 μs (116.5 μs .. 117.3 μs)+ 0.999 R² (0.998 R² .. 1.000 R²)+mean 118.6 μs (116.6 μs .. 126.6 μs)+std dev 13.17 μs (866.0 ns .. 27.98 μs)+variance introduced by outliers: 84% (severely inflated)++benchmarking load/loadToml+time 2.801 ms (2.763 ms .. 2.833 ms)+ 0.998 R² (0.995 R² .. 1.000 R²)+mean 2.890 ms (2.834 ms .. 3.056 ms)+std dev 266.0 μs (45.31 μs .. 481.7 μs)+variance introduced by outliers: 63% (severely inflated)+```++#### Parse Performance++```log+benchmarking parse-int/int+time 1.285 μs (1.280 μs .. 1.291 μs)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 1.294 μs (1.289 μs .. 1.300 μs)+std dev 18.29 ns (13.86 ns .. 26.49 ns)+variance introduced by outliers: 13% (moderately inflated)++benchmarking parse-int/int/text+time 593.9 ns (592.4 ns .. 595.6 ns)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 595.8 ns (594.0 ns .. 598.8 ns)+std dev 7.536 ns (5.243 ns .. 10.81 ns)+variance introduced by outliers: 12% (moderately inflated)++benchmarking parse-int/int/bool+time 1.067 μs (1.064 μs .. 1.070 μs)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 1.068 μs (1.065 μs .. 1.072 μs)+std dev 10.28 ns (7.972 ns .. 13.55 ns)++benchmarking run/text+time 953.9 ns (951.3 ns .. 957.1 ns)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 954.7 ns (952.6 ns .. 958.4 ns)+std dev 8.659 ns (5.963 ns .. 13.47 ns)++benchmarking run/bool+time 1.218 μs (1.214 μs .. 1.222 μs)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 1.216 μs (1.213 μs .. 1.221 μs)+std dev 13.03 ns (9.765 ns .. 18.64 ns)+```++#### Parse IO Performance++```log+benchmarking parse-io/read-io+time 7.803 ns (7.785 ns .. 7.822 ns)+ 1.000 R² (1.000 R² .. 1.000 R²)+mean 7.812 ns (7.797 ns .. 7.838 ns)+std dev 68.51 ps (41.76 ps .. 118.5 ps)++benchmarking parse-io/parse-io+time 2.286 μs (1.702 μs .. 3.317 μs)+ 0.494 R² (0.456 R² .. 0.908 R²)+mean 2.856 μs (2.243 μs .. 3.872 μs)+std dev 2.663 μs (1.837 μs .. 3.365 μs)+variance introduced by outliers: 99% (severely inflated)+```++As showed above, salak's performance is good enough for normal applications. Normally loading and parsing properties can be completed in less then 5ms. Also salak's `require` function support parsing `IO a` values, which can be used for dynamic values affected by reloading. Reading the wrapped `IO` value is much faster then `require`.+ ## Usage Environment:
bench/SalakBench.hs view
@@ -3,7 +3,9 @@ import Control.Monad.Reader import Criterion.Main import Data.Default-import Data.Text (Text)+import Data.Text (Text)+import Data.Time+import Data.Time.Clock.System import Salak @@ -30,6 +32,10 @@ , bgroup "run" [ bench "text" $ whnfIO $ (run $ require "a.b.c.d.e.f.g.h.i.j.k.text" :: IO Text) , bench "bool" $ whnfIO $ (run $ require "a.b.c.d.e.f.g.h.i.j.k.bool" :: IO Bool)+ ]+ , bgroup "gettime"+ [ bench "current" $ whnfIO getCurrentTime+ , bench "system" $ whnfIO getSystemTime ] ]
salak.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 21d8970596a92e37060854c66cf0d1e92ceb5810194de8a348cf9d3d9bf37112+-- hash: 3b11a5cf0761804166bde937f74cb9280c69f018e509879be1b8711d49ac58c0 name: salak-version: 0.3.5.1+version: 0.3.5.2 synopsis: Configuration (re)Loader and Parser. category: Library, Configuration homepage: https://github.com/leptonyu/salak#readme@@ -64,42 +64,21 @@ Salak.Internal.PropSpec Salak.Internal.SourceSpec Salak.TrieSpec- Salak- Salak.Internal- Salak.Internal.Key- Salak.Internal.Prop- Salak.Internal.Source- Salak.Internal.Val- Salak.Internal.Writable- Salak.Trie Paths_salak hs-source-dirs: test- src default-extensions: BangPatterns CPP DefaultSignatures DeriveFunctor DeriveGeneric FlexibleContexts FlexibleInstances GeneralizedNewtypeDeriving MultiParamTypeClasses NoOverloadedLists OverloadedStrings RankNTypes RecordWildCards ScopedTypeVariables TupleSections TypeOperators ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures -rtsopts -threaded -with-rtsopts=-K1K build-depends: QuickCheck <2.14 , base >=4.10 && <5- , bytestring >=0.10.8 && <0.11- , containers >=0.6.0 && <0.7- , data-default >=0.7.1 && <0.8- , directory >=1.3.3 && <1.4- , dlist >=0.8.0 && <0.9- , exceptions >=0.10.2 && <0.11- , filepath >=1.4.2 && <1.5- , hashable >=1.2.7.0 && <1.4- , heaps >=0.3.6 && <0.4 , hspec ==2.*- , megaparsec >=7.0.5 && <7.1- , menshen >=0.0.3 && <0.1 , mtl >=2.2.2 && <2.3 , random- , scientific >=0.3.6 && <0.4+ , salak+ , scientific , text >=1.2.3 && <1.3- , time >=1.8.0 && <1.10- , unliftio-core >=0.1.2 && <0.2- , unordered-containers >=0.2.10 && <0.3+ , unordered-containers default-language: Haskell2010 build-tool-depends: hspec-discover:hspec-discover @@ -114,23 +93,10 @@ ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures -rtsopts -threaded -with-rtsopts=-K1K build-depends: base >=4.10 && <5- , bytestring >=0.10.8 && <0.11- , containers >=0.6.0 && <0.7 , criterion- , data-default >=0.7.1 && <0.8- , directory >=1.3.3 && <1.4- , dlist >=0.8.0 && <0.9- , exceptions >=0.10.2 && <0.11- , filepath >=1.4.2 && <1.5- , hashable >=1.2.7.0 && <1.4- , heaps >=0.3.6 && <0.4- , megaparsec >=7.0.5 && <7.1- , menshen >=0.0.3 && <0.1+ , data-default , mtl >=2.2.2 && <2.3 , salak- , scientific >=0.3.6 && <0.4 , text >=1.2.3 && <1.3- , time >=1.8.0 && <1.10- , unliftio-core >=0.1.2 && <0.2- , unordered-containers >=0.2.10 && <0.3+ , time default-language: Haskell2010
src/Salak/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies #-} -- | -- Module: Salak.Internal -- Copyright: 2019 Daniel YU@@ -35,10 +35,16 @@ , setVal , Val(..) , Value(..)+ , VRef(..)+ , mkValue , ToValue(..) , liftNT , SourcePack(..) , MonadIO+ , runProp+ , withKeys+ , extract+ , genSource , module Salak.Internal.Writable ) where @@ -150,7 +156,7 @@ -- | Simple loader loadList :: (MonadThrow m, MonadIO m, Foldable f, ToKeys k, ToValue v) => Bool -> String -> IO (f (k,v)) -> LoadSalakT m ()-loadList canReload name iof = loadTrie canReload name (\i -> gen i <$> iof)+loadList canReload name iof = loadTrie canReload name (\i -> genSource i <$> iof) -- | Standard salak functions, by load and with a `SourcePack` instance. -- Users should use `SourcePack` to create custom `MonadSalak` instances, then you get will an instance of `MonadSalak`.
src/Salak/Internal/Prop.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies #-} module Salak.Internal.Prop where import Control.Applicative ((<|>))@@ -111,8 +111,9 @@ a <|> b = do v <- try a case v of- Right x -> return x- Left (_ :: SomeException) -> b+ Right x -> return x+ Left (NullException _) -> b+ Left e -> throwM e instance Monad m => MonadError SomeException (Prop m) where {-# INLINE throwError #-}
src/Salak/Internal/Source.hs view
@@ -61,8 +61,8 @@ {-# INLINE list #-} list = fmap (\(k,v)->(show k,v)) $ T.toList $ fmap fst t -gen :: (Foldable f, ToKeys k, ToValue v) => Int -> f (k,v) -> TraceSource-gen i = foldr go T.empty+genSource :: (Foldable f, ToKeys k, ToValue v) => Int -> f (k,v) -> TraceSource+genSource i = foldr go T.empty where {-# INLINE go #-} go (k,v) x = case toKeys k of
test/Salak/Internal/KeySpec.hs view
@@ -1,8 +1,8 @@ module Salak.Internal.KeySpec(spec) where -import Data.List (intercalate)-import Data.Text (Text, pack, unpack)-import Salak.Internal.Key+import Data.List (intercalate)+import Data.Text (Text, pack, unpack)+import Salak.Internal import Test.Hspec import Test.QuickCheck
test/Salak/Internal/PropSpec.hs view
@@ -8,10 +8,15 @@ import Data.Word import Salak import Salak.Internal-import Salak.Internal.Prop-import Salak.Internal.Val import Test.Hspec +data Conf = Conf+ { val :: Int+ }++instance FromProp m Conf where+ fromProp = Conf <$> "val" .?= 1+ spec :: SpecWith () spec = do context "Prop" $ do@@ -27,6 +32,8 @@ , ("bool-L4", "FALSE") , ("int-", "-1") , ("empty", "")+ , ("a.val", "")+ , ("b.val", "wrong") ] run :: ((forall a. FromProp IO a => Text -> IO a) -> RunSalak ()) -> IO () run g = loadAndRunSalak (loadMock vals) $ do@@ -103,6 +110,11 @@ (v :: String) `shouldBe` "" (vm :: Maybe String) `shouldBe` Just "" (n :: Maybe String) `shouldBe` Nothing+ it "<|>" $ run $ \r -> do+ Conf{..} <- require "a"+ lift $ do+ val `shouldBe` 1+ (r "b" :: IO Conf) `shouldThrow` anyException context "placeholder" $ do it "positive" $ do mkValue (VT "${}") `shouldBe` Right (VR [VRR "" []])
test/Salak/Internal/SourceSpec.hs view
@@ -1,16 +1,15 @@ module Salak.Internal.SourceSpec(spec) where +import Control.Concurrent.MVar import Control.Monad.Writer-import Data.Text (Text, unpack)+import Data.Text (Text, unpack) import GHC.Generics import Salak import Salak.Internal-import Salak.Internal.Source-import qualified Salak.Trie as T-import System.Random (randomIO)+import qualified Salak.Trie as T+import System.Random (randomIO) import Test.Hspec import Test.QuickCheck-import Control.Concurrent.MVar data Config = Config@@ -39,11 +38,11 @@ spec = do context "source" $ do it "normal - 1" $ do- let (_,b,c) = extract T.empty $ gen 0 ([("hello", "world")] :: [(Text, Text)])+ let (_,b,c) = extract T.empty $ genSource 0 ([("hello", "world")] :: [(Text, Text)]) length c `shouldBe` 0 length (T.toList b) `shouldBe` 1 it "normal - 2" $ do- let (_,b,c) = extract T.empty $ gen 0 ([("hello.value", "world")] :: [(Text, Text)])+ let (_,b,c) = extract T.empty $ genSource 0 ([("hello.value", "world")] :: [(Text, Text)]) length c `shouldBe` 0 length (T.toList b) `shouldBe` 1 context "Reload test" $ do@@ -100,5 +99,43 @@ msgs `shouldBe` ["hello:Add"] v <- vio v `shouldBe` 8+ it "reload - multi layer" $ do+ io0 <- newMVar [("hello", "10")]+ io1 <- newMVar [("hello", "8")]+ let+ lio = do+ loadList True "test-0" (readMVar io0 :: IO [(Text, Text)])+ loadList True "test-1" (readMVar io1 :: IO [(Text, Text)])+ loadAndRunSalak lio $ do+ vio <- require "hello"+ rl <- askReload+ lift $ do+ v <- vio :: IO Int+ v `shouldBe` 10+ lift $ do+ void $ swapMVar io0 [("hello", "7")]+ _ <- rl+ v <- vio :: IO Int+ v `shouldBe` 7+ lift $ do+ void $ swapMVar io1 [("hello", "81")]+ _ <- rl+ v <- vio :: IO Int+ v `shouldBe` 7+ lift $ do+ void $ swapMVar io0 []+ _ <- rl+ v <- vio :: IO Int+ v `shouldBe` 81+ lift $ do+ void $ swapMVar io1 [("hello", "82")]+ _ <- rl+ v <- vio :: IO Int+ v `shouldBe` 82+ lift $ do+ void $ swapMVar io0 [("hello", "10")]+ _ <- rl+ v <- vio :: IO Int+ v `shouldBe` 10
test/Salak/TrieSpec.hs view
@@ -1,7 +1,7 @@ module Salak.TrieSpec(spec) where import qualified Data.HashMap.Strict as HM-import Salak.Internal.Key+import Salak.Internal import qualified Salak.Trie as T import Test.Hspec