summaryrefslogtreecommitdiff
path: root/test/bench.hs
blob: 9952ec2c5b1bdf66c4c80c26e595ab08e80e8161 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{-# LANGUAGE ForeignFunctionInterface #-}
import qualified Data.Attoparsec.Text       as Atto
import qualified Data.ByteString.Char8      as S
import qualified Data.ByteString.Lazy.Char8 as L
import Data.List as List
import Data.Either
import Data.ByteString.Unsafe
import Data.Text
import Data.Text.Encoding
import Data.Word
import Foreign.Ptr
import System.IO.Unsafe
import qualified Data.Vector as V
import Control.Monad.State ( State, execState, gets, modify )
import qualified Data.IntMap as IntMap

import Codec.Wavefront.Lexer ( lexer )
import Codec.Wavefront.Object ( WavefrontOBJ, ctxtToWavefrontOBJ, objLocations )
import Codec.Wavefront.Token ( tokenize )

import qualified Graphics.WaveFront.Parse as Parse
import qualified Graphics.WaveFront.Parse.Common as Parse

import Wavefront

import Criterion.Main
import Weigh -- WARNING: weigh is incompatible with profiling. It reports much more allocations with profiling turned on.

foreign import ccall "&cube_obj" cube_ptr :: Ptr Word8
cube_obj_len :: Int
cube_obj_len = 840

cube_obj :: L.ByteString
cube_obj = L.fromChunks . pure . unsafePerformIO $ do
    unsafePackCStringFinalizer cube_ptr cube_obj_len (return ())
{-# NOINLINE cube_obj #-}

cube_objT :: Text
cube_objT = decodeASCII $ L.toStrict cube_obj
{-# NOINLINE cube_objT #-}

countVerticesSabadie :: Text -> Int
countVerticesSabadie ts = V.length vs
 where
    obj = sabadie ts
    vs = either (const V.empty) objLocations obj

countVerticesSundqvist :: Text -> Int
countVerticesSundqvist ts = List.length vs
 where
    obj = sundqvist ts
    vs = either (const []) (List.filter isOBJVertex) obj
    isOBJVertex (Parse.OBJVertex {}) = True
    isOBJVertex _                    = False

countVerticesCrayne :: L.ByteString -> Int
countVerticesCrayne bs = execState (parseOBJ builder (ObjConfig IntMap.empty) bs) 0
 where
    builder = nullBuilder
        { vertex = \_ -> modify succ
        }

sabadie :: Text -> Either String WavefrontOBJ
sabadie = fmap (ctxtToWavefrontOBJ . lexer) . tokenize

sundqvist :: Text -> Either String (Parse.OBJ Double Text Integer [])
sundqvist = Atto.parseOnly (Parse.wholeFile Parse.obj)

main :: IO ()
main = do
    print $ countVerticesSabadie cube_objT
    print $ countVerticesSundqvist cube_objT
    print $ countVerticesCrayne cube_obj
    putStrLn $ "---- Benchmarking"
    defaultMain [
          bgroup "count vertices"
                [ bench "crayne" $ whnf countVerticesCrayne cube_obj
                , bench "sabadie"   $ whnf countVerticesSabadie   cube_objT
                , bench "sundqvist" $ whnf countVerticesSundqvist cube_objT
                ]
          ]
    return ()