crypto-cipher-benchmarks (empty) → 0.0.1
raw patch · 4 files changed
+255/−0 lines, 4 filesdep +basedep +byteabledep +bytestringsetup-changed
Dependencies added: base, byteable, bytestring, criterion, crypto-cipher-types, mtl, pretty, securemem
Files
- Crypto/Cipher/Benchmarks.hs +195/−0
- LICENSE +27/−0
- Setup.hs +2/−0
- crypto-cipher-benchmarks.cabal +31/−0
+ Crypto/Cipher/Benchmarks.hs view
@@ -0,0 +1,195 @@+-- |+-- Module : Crypto.Cipher.Benchmarks+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : Stable+-- Portability : Excellent+--+-- benchmarks for symmetric ciphers+--+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE Rank2Types #-}+module Crypto.Cipher.Benchmarks+ ( defaultMain+ , GBlockCipher(..)+ ) where++import Control.Applicative+import Criterion+import Criterion.Environment+import Criterion.Config hiding (Help)+import Criterion.Monad+import Criterion.Analysis+import Criterion.Measurement++import Text.Printf+import Text.PrettyPrint hiding (Mode, mode)++import Data.Maybe+import Control.Monad.Trans++import qualified Data.ByteString as B++import Crypto.Cipher.Types++import System.Console.GetOpt+import System.Environment+import System.Exit++import Data.Char (toUpper)++-- | Generic Block cipher that wrap a specific block cipher.+data GBlockCipher = forall a . BlockCipher a => GBlockCipher a++data Mode = ECB+ | CBC+ | CTR+ | XTS+ | OCB+ | CCM+ | EAX+ | CWC+ | GCM+ deriving (Show, Enum, Bounded)++defaultSzs :: [Int]+defaultSzs = [16,32,128,512,1024,4096,16384]++defaultModes :: [Mode]+defaultModes = [minBound..]++doCipher :: Environment -> Int -> [Int] -> (B.ByteString -> B.ByteString) -> Criterion [Double]+doCipher env nbIter szs f = mapM getMeanFromBench szs+ where getMeanFromBench sz =+ runBenchmark env (whnf f $ B.replicate sz 0) >>= \sample ->+ analyseMean sample nbIter >>= return++modeToBench :: BlockCipher cipher => cipher -> Mode -> Maybe (B.ByteString -> B.ByteString)+modeToBench cipher ECB = Just $ ecbEncrypt cipher+modeToBench cipher CBC = Just $ cbcEncrypt cipher nullIV+modeToBench cipher CTR = Just $ ctrCombine cipher nullIV+modeToBench cipher XTS = Just $ xtsEncrypt (cipher, cipher) nullIV 0+modeToBench cipher OCB = benchAEAD cipher AEAD_OCB+modeToBench cipher GCM = benchAEAD cipher AEAD_GCM+modeToBench cipher CCM = benchAEAD cipher AEAD_CCM+modeToBench cipher CWC = benchAEAD cipher AEAD_CWC+modeToBench cipher EAX = benchAEAD cipher AEAD_EAX++benchAEAD :: BlockCipher cipher => cipher -> AEADMode -> Maybe (B.ByteString -> B.ByteString)+benchAEAD cipher mode = (\aead -> (\b -> snd $ aeadSimpleEncrypt aead B.empty b (blockSize cipher))) `fmap` aeadInit mode cipher (B.replicate (blockSize cipher) 0)++modesToBench :: BlockCipher cipher => cipher -> [Mode] -> [(Mode, B.ByteString -> B.ByteString)]+modesToBench cipher = reverse . foldl (\acc mode -> case modeToBench cipher mode of+ Just fb -> (mode, fb) : acc+ Nothing -> acc) []++data Report = Report+ { reportSz :: Int+ , reportMean :: Double+ , reportSecs :: String+ , reportSpeed :: Double+ , reportSpeedS :: String+ } deriving (Show)++doOne :: Int -> Environment -> [Int] -> String -> (B.ByteString -> B.ByteString) -> Criterion (String, [Report])+doOne iters env szs name f = do+ means <- doCipher env iters szs f+ return (name, map toReport $ zip means szs)+ where toReport (mean, sz) = Report+ { reportSz = sz+ , reportMean = mean+ , reportSecs = secs mean+ , reportSpeed = norm sz mean+ , reportSpeedS = pn (norm sz mean)+ }++ norm :: Int -> Double -> Double+ norm n meanTime+ | n < 1024 = 1.0 / (meanTime * (1024 / fromIntegral n))+ | n == 1024 = 1.0 / meanTime+ | otherwise = 1.0 / (meanTime / (fromIntegral n / 1024))++ pn :: Double -> String+ pn val+ | val > (10 * 1024) = printf "%.1f M/s" (val / 1024)+ | otherwise = printf "%.1f K/s" val+++runBench :: Int -> Bool -> [Int] -> [Mode] -> [GBlockCipher] -> Criterion ()+runBench iters showTime szs modes ciphers = do+ env <- measureEnvironment+ reports <- concat <$> mapM (runBenchCipher env) ciphers+ let docHeader = col1 "cipher name" <+> hsep (map (textOf 12 . show) szs)+ let doc = vcat (docHeader : map toLine reports)+ + liftIO $ putStrLn $ show doc+ + where runBenchCipher env (GBlockCipher cipher) = do+ let name = cipherName cipher+ benchs = modesToBench cipher modes+ mapM (\(benchMode, benchF) -> doOne iters env szs (name ++ "-" ++ show benchMode) benchF) benchs+ toLine (name, szReports) =+ hsep (col1 name : map field szReports)+ field | showTime = textOf 12 . reportSecs+ | otherwise = textOf 12 . reportSpeedS+ textOf n s | len == n = text s+ | len < n = text (s ++ replicate (n - len) ' ')+ | otherwise = text (take n s)+ where len = length s+ col1 = textOf 14+ +data OptionArg = SizeArg String+ | CipherArg String+ | ModeArg String+ | Iter String+ | Time+ | Help+ deriving (Show,Eq)++wordsWhen :: (Char -> Bool) -> String -> [String]+wordsWhen p s =+ case dropWhile p s of+ "" -> []+ s' -> w : wordsWhen p s''+ where (w, s'') = break p s'++instanciateCiphers :: [GBlockCipher] -> [GBlockCipher]+instanciateCiphers ciphers = map proxy ciphers+ where proxy :: GBlockCipher -> GBlockCipher+ proxy (GBlockCipher c) = GBlockCipher $ instanciate c+ instanciate :: BlockCipher a => a -> a+ instanciate c =+ let bs = case cipherKeySize c of+ Nothing -> B.replicate 1 0+ Just sz -> B.replicate sz 1+ in cipherInit (fromJust $ makeKey bs)++-- | DefaultMain: parse command line arguments, run benchmarks+-- and report+defaultMain :: [GBlockCipher] -> IO ()+defaultMain ciphers = do+ args <- getArgs+ case getOpt Permute opts args of+ (os,_,[]) | Help `elem` os -> do putStrLn (usageInfo "crypto-cipher-benchmark" opts)+ exitFailure+ | otherwise -> do let (ss, ms, iters) = foldl (\(sp, mp, it) o ->+ case o of+ SizeArg s -> (map read $ wordsWhen (== ',') s, mp, it)+ ModeArg s -> let modes = wordsWhen (== ',') $ map toUpper s+ nm = filter (\m -> show m `elem` modes) mp+ in (sp, nm, it)+ Iter s -> (sp, mp, read s)+ CipherArg _ -> (sp, mp, it)+ _ -> (sp, mp, it)+ + ) (defaultSzs, defaultModes, 100) os+ withConfig defaultConfig $ runBench iters (Time `elem` os) ss ms (instanciateCiphers ciphers)+ (_,_,err) -> error (show err)+ where opts =+ [ Option ['n'] ["iter"] (ReqArg Iter "iteration") "number of iterations per benchmarks"+ , Option [] ["size"] (ReqArg SizeArg "size") "size to run (csv)"+ , Option [] ["cipher"] (ReqArg CipherArg "cipher") "cipher to run (csv)"+ , Option [] ["mode"] (ReqArg ModeArg "mode") "mode to run (csv)"+ , Option ['t'] ["time"] (NoArg Time) "show average time instead of average speed"+ , Option ['h'] ["help"] (NoArg Help) "get help"+ ]
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2013 Vincent Hanquez <vincent@snarc.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ crypto-cipher-benchmarks.cabal view
@@ -0,0 +1,31 @@+Name: crypto-cipher-benchmarks+Version: 0.0.1+Synopsis: Generic cryptography cipher benchmarks+Description: Generic cryptography cipher benchmarks+License: BSD3+License-file: LICENSE+Copyright: Vincent Hanquez <vincent@snarc.org>+Author: Vincent Hanquez <vincent@snarc.org>+Maintainer: vincent@snarc.org+Category: Cryptography+Stability: experimental+Build-Type: Simple+Homepage: http://github.com/vincenthz/hs-crypto-cipher+Cabal-Version: >=1.8++Library+ Exposed-modules: Crypto.Cipher.Benchmarks+ Build-depends: base >= 4 && < 5+ , bytestring+ , byteable >= 0.1.1+ , securemem >= 0.1.1+ , criterion+ , crypto-cipher-types+ , mtl+ , pretty+ ghc-options: -Wall -fwarn-tabs++source-repository head+ type: git+ location: git://github.com/vincenthz/hs-crypto-cipher+ subdir: benchs