diff options
author | Joe Crayne <joe@jerkface.net> | 2019-06-12 19:39:29 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2019-06-12 19:39:29 -0400 |
commit | 6ee08be31b394b54f77c243a3691864e9e229f43 (patch) | |
tree | d0c6e2109096b2dca508fae139f253933d645c53 | |
parent | 550c43c8491e2b6a2873caf8e9c032b69e56e03f (diff) |
benchmarks
-rw-r--r-- | src/Wavefront.hs | 33 | ||||
-rw-r--r-- | test/bench.hs | 82 | ||||
-rw-r--r-- | test/cube.c | 54 | ||||
-rw-r--r-- | wavefront-obj.cabal | 6 |
4 files changed, 175 insertions, 0 deletions
diff --git a/src/Wavefront.hs b/src/Wavefront.hs index 66d6cdb..9e42779 100644 --- a/src/Wavefront.hs +++ b/src/Wavefront.hs | |||
@@ -42,6 +42,39 @@ data ObjBuilder m = ObjBuilder | |||
42 | , badToken :: L.ByteString -> m () | 42 | , badToken :: L.ByteString -> m () |
43 | } | 43 | } |
44 | 44 | ||
45 | nullBuilder :: Applicative m => ObjBuilder m | ||
46 | nullBuilder = ObjBuilder | ||
47 | { vertex = \vs -> pure () | ||
48 | , vertexT = \vs -> pure () | ||
49 | , vertexN = \vs -> pure () | ||
50 | , vertexP = \vs -> pure () | ||
51 | , face = \is -> pure () | ||
52 | , cstype = \isRat typ -> pure () | ||
53 | , curv2 = \is -> pure () | ||
54 | , curv = \u0 v0 is -> pure () | ||
55 | , parm = \isU is -> pure () | ||
56 | , specialPoints = \is -> pure () | ||
57 | , endFreeForm = pure () | ||
58 | , ctech = \approx -> pure () | ||
59 | , stech = \approx -> pure () | ||
60 | , deg = \is -> pure () | ||
61 | , surf = \u0 u1 v0 v1 ts -> pure () | ||
62 | , trim = \ss -> pure () | ||
63 | , hole = \ss -> pure () | ||
64 | , specialCurves = \ss -> pure () | ||
65 | , equivalentCurves = \ccs -> pure () | ||
66 | , groups = \gs -> pure () | ||
67 | , smoothingGroup = \sg -> pure () | ||
68 | , mergingGroup = \mg δ -> pure () | ||
69 | , usemtl = \mtl -> pure () | ||
70 | , deprecated_cdc = \is -> pure () | ||
71 | , deprecated_bzp = \is -> pure () | ||
72 | , mtllib = \fns -> pure () | ||
73 | , objectName = \obn -> pure () | ||
74 | , badToken = \bs -> pure () | ||
75 | } | ||
76 | |||
77 | |||
45 | data CurveSamplingSpec | 78 | data CurveSamplingSpec |
46 | -- ctech cparm | 79 | -- ctech cparm |
47 | = UniformSubdivision | 80 | = UniformSubdivision |
diff --git a/test/bench.hs b/test/bench.hs new file mode 100644 index 0000000..9952ec2 --- /dev/null +++ b/test/bench.hs | |||
@@ -0,0 +1,82 @@ | |||
1 | {-# LANGUAGE ForeignFunctionInterface #-} | ||
2 | import qualified Data.Attoparsec.Text as Atto | ||
3 | import qualified Data.ByteString.Char8 as S | ||
4 | import qualified Data.ByteString.Lazy.Char8 as L | ||
5 | import Data.List as List | ||
6 | import Data.Either | ||
7 | import Data.ByteString.Unsafe | ||
8 | import Data.Text | ||
9 | import Data.Text.Encoding | ||
10 | import Data.Word | ||
11 | import Foreign.Ptr | ||
12 | import System.IO.Unsafe | ||
13 | import qualified Data.Vector as V | ||
14 | import Control.Monad.State ( State, execState, gets, modify ) | ||
15 | import qualified Data.IntMap as IntMap | ||
16 | |||
17 | import Codec.Wavefront.Lexer ( lexer ) | ||
18 | import Codec.Wavefront.Object ( WavefrontOBJ, ctxtToWavefrontOBJ, objLocations ) | ||
19 | import Codec.Wavefront.Token ( tokenize ) | ||
20 | |||
21 | import qualified Graphics.WaveFront.Parse as Parse | ||
22 | import qualified Graphics.WaveFront.Parse.Common as Parse | ||
23 | |||
24 | import Wavefront | ||
25 | |||
26 | import Criterion.Main | ||
27 | import Weigh -- WARNING: weigh is incompatible with profiling. It reports much more allocations with profiling turned on. | ||
28 | |||
29 | foreign import ccall "&cube_obj" cube_ptr :: Ptr Word8 | ||
30 | cube_obj_len :: Int | ||
31 | cube_obj_len = 840 | ||
32 | |||
33 | cube_obj :: L.ByteString | ||
34 | cube_obj = L.fromChunks . pure . unsafePerformIO $ do | ||
35 | unsafePackCStringFinalizer cube_ptr cube_obj_len (return ()) | ||
36 | {-# NOINLINE cube_obj #-} | ||
37 | |||
38 | cube_objT :: Text | ||
39 | cube_objT = decodeASCII $ L.toStrict cube_obj | ||
40 | {-# NOINLINE cube_objT #-} | ||
41 | |||
42 | countVerticesSabadie :: Text -> Int | ||
43 | countVerticesSabadie ts = V.length vs | ||
44 | where | ||
45 | obj = sabadie ts | ||
46 | vs = either (const V.empty) objLocations obj | ||
47 | |||
48 | countVerticesSundqvist :: Text -> Int | ||
49 | countVerticesSundqvist ts = List.length vs | ||
50 | where | ||
51 | obj = sundqvist ts | ||
52 | vs = either (const []) (List.filter isOBJVertex) obj | ||
53 | isOBJVertex (Parse.OBJVertex {}) = True | ||
54 | isOBJVertex _ = False | ||
55 | |||
56 | countVerticesCrayne :: L.ByteString -> Int | ||
57 | countVerticesCrayne bs = execState (parseOBJ builder (ObjConfig IntMap.empty) bs) 0 | ||
58 | where | ||
59 | builder = nullBuilder | ||
60 | { vertex = \_ -> modify succ | ||
61 | } | ||
62 | |||
63 | sabadie :: Text -> Either String WavefrontOBJ | ||
64 | sabadie = fmap (ctxtToWavefrontOBJ . lexer) . tokenize | ||
65 | |||
66 | sundqvist :: Text -> Either String (Parse.OBJ Double Text Integer []) | ||
67 | sundqvist = Atto.parseOnly (Parse.wholeFile Parse.obj) | ||
68 | |||
69 | main :: IO () | ||
70 | main = do | ||
71 | print $ countVerticesSabadie cube_objT | ||
72 | print $ countVerticesSundqvist cube_objT | ||
73 | print $ countVerticesCrayne cube_obj | ||
74 | putStrLn $ "---- Benchmarking" | ||
75 | defaultMain [ | ||
76 | bgroup "count vertices" | ||
77 | [ bench "crayne" $ whnf countVerticesCrayne cube_obj | ||
78 | , bench "sabadie" $ whnf countVerticesSabadie cube_objT | ||
79 | , bench "sundqvist" $ whnf countVerticesSundqvist cube_objT | ||
80 | ] | ||
81 | ] | ||
82 | return () | ||
diff --git a/test/cube.c b/test/cube.c new file mode 100644 index 0000000..952f32e --- /dev/null +++ b/test/cube.c | |||
@@ -0,0 +1,54 @@ | |||
1 | |||
2 | unsigned char cube_obj[] = | ||
3 | " \n" | ||
4 | " \n" | ||
5 | // For now, sabadie parser has bug and cannot handle leading comments. | ||
6 | // "# cube.obj\n" | ||
7 | // "#\n" | ||
8 | "\n" | ||
9 | "o cube\n" | ||
10 | "mtllib cube.mtl\n" | ||
11 | "\n" | ||
12 | "v -0.500000 -0.500000 0.500000\n" | ||
13 | "v 0.500000 -0.500000 0.500000\n" | ||
14 | "v -0.500000 0.500000 0.500000\n" | ||
15 | "v 0.500000 0.500000 0.500000\n" | ||
16 | "v -0.500000 0.500000 -0.500000\n" | ||
17 | "v 0.500000 0.500000 -0.500000\n" | ||
18 | "v -0.500000 -0.500000 -0.500000\n" | ||
19 | "v 0.500000 -0.500000 -0.500000\n" | ||
20 | "\n" | ||
21 | "vt 0.000000 0.000000\n" | ||
22 | "vt 1.000000 0.000000\n" | ||
23 | "vt 0.000000 1.000000\n" | ||
24 | "vt 1.000000 1.000000\n" | ||
25 | "\n" | ||
26 | "vn 0.000000 0.000000 1.000000\n" | ||
27 | "vn 0.000000 1.000000 0.000000\n" | ||
28 | "vn 0.000000 0.000000 -1.000000\n" | ||
29 | "vn 0.000000 -1.000000 0.000000\n" | ||
30 | "vn 1.000000 0.000000 0.000000\n" | ||
31 | "vn -1.000000 0.000000 0.000000\n" | ||
32 | "\n" | ||
33 | "g cube\n" | ||
34 | "usemtl material0\n" | ||
35 | "s 1\n" | ||
36 | "f 1/1/1 2/2/1 3/3/1\n" | ||
37 | "f 3/3/1 2/2/1 4/4/1\n" | ||
38 | "s 2\n" | ||
39 | "f 3/1/2 4/2/2 5/3/2\n" | ||
40 | "f 5/3/2 4/2/2 6/4/2\n" | ||
41 | "s 3\n" | ||
42 | "f 5/4/3 6/3/3 7/2/3\n" | ||
43 | "f 7/2/3 6/3/3 8/1/3\n" | ||
44 | "s 4\n" | ||
45 | "f 7/1/4 8/2/4 1/3/4\n" | ||
46 | "f 1/3/4 8/2/4 2/4/4\n" | ||
47 | "s 5\n" | ||
48 | "f 2/1/5 8/2/5 4/3/5\n" | ||
49 | "f 4/3/5 8/2/5 6/4/5\n" | ||
50 | "s 6\n" | ||
51 | "f 7/1/6 1/2/6 5/3/6\n" | ||
52 | "f 5/3/6 1/2/6 3/4/6\n"; | ||
53 | |||
54 | unsigned int cube_obj_len = 840; | ||
diff --git a/wavefront-obj.cabal b/wavefront-obj.cabal index 612d6f5..a1087df 100644 --- a/wavefront-obj.cabal +++ b/wavefront-obj.cabal | |||
@@ -92,3 +92,9 @@ library | |||
92 | 92 | ||
93 | hs-source-dirs: src | 93 | hs-source-dirs: src |
94 | default-language: Haskell2010 | 94 | default-language: Haskell2010 |
95 | |||
96 | executable bench | ||
97 | main-is: test/bench.hs | ||
98 | C-sources: test/cube.c | ||
99 | ghc-options: -Wall -rtsopts | ||
100 | build-depends: base, bytestring, attoparsec, text, vector, transformers, mtl, containers, wavefront-obj, criterion, weigh | ||