Skip to content

Instantly share code, notes, and snippets.

@tfausak
Last active July 25, 2017 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tfausak/0c90ed1b450ae84136c110f026e16bc6 to your computer and use it in GitHub Desktop.
Save tfausak/0c90ed1b450ae84136c110f026e16bc6 to your computer and use it in GitHub Desktop.
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Deriving where
import Data.Data (Data)
import Data.Int (Int8, Int32)
import Data.Typeable (Typeable)
import Data.Word (Word, Word8, Word16, Word32, Word64)
data Replay = Replay
{ replayHeader :: Section Header
, replayContent :: Section Content
} deriving (CLASSES)
data Section body = Section
{ sectionSize :: Word32
, sectionCrc :: Word32
, sectionBody :: body
} deriving (CLASSES)
data Header = Header
{ headerMajorVersion :: Word32
, headerMinorVersion :: Word32
, headerLabel :: String
, headerProperties :: Dictionary Property
} deriving (CLASSES)
data Dictionary value = Dictionary
{ dictionaryElements :: [(String, value)]
, dictionaryLastKey :: String
} deriving (CLASSES)
data Property = Property
{ propertyKind :: String
, propertySize :: Word64
, propertyValue :: PropertyValue Property
} deriving (CLASSES)
data PropertyValue value
= ArrayPropertyValue [Dictionary value]
| BoolPropertyValue Word8
| BytePropertyValue String (Maybe String)
| FloatPropertyValue Float
| IntPropertyValue Int32
| NamePropertyValue String
| QWordPropertyValue Word64
| StrPropertyValue String
deriving (CLASSES)
data Content = Content
{ contentLevels :: [String]
, contentKeyFrames :: [KeyFrame]
, contentStreamSize :: Word32
, contentFrames :: [Frame]
, contentMessages :: [Message]
, contentMarks :: [Mark]
, contentPackages :: [String]
, contentObjects :: [String]
, contentNames :: [String]
, contentClassMappings :: [ClassMapping]
, contentCaches :: [Cache]
} deriving (CLASSES)
data KeyFrame = KeyFrame
{ keyFrameTime :: Float
, keyFrameFrame :: Word32
, keyFramePosition :: Word32
} deriving (CLASSES)
data Frame = Frame
{ frameTime :: Float
, frameDelta :: Float
, frameReplications :: [Replication]
} deriving (CLASSES)
data Replication = Replication
{ replicationActorId :: CompressedWord
, replicationValue :: ReplicationValue
} deriving (CLASSES)
data CompressedWord = CompressedWord
{ compressedWordLimit :: Word
, compressedWordValue :: Word
} deriving (CLASSES)
data ReplicationValue
= SpawnedReplicationValue SpawnedReplication
| UpdatedReplicationValue UpdatedReplication
| DestroyedReplicationValue DestroyedReplication
deriving (CLASSES)
data SpawnedReplication = SpawnedReplication
{ spawnedReplicationFlag :: Bool
, spawnedReplicationNameIndex :: Maybe Word32
, spawnedReplicationName :: Maybe String
, spawnedReplicationObjectId :: Word32
, spawnedReplicationObjectName :: String
, spawnedReplicationClassName :: String
, spawnedReplicationInitialization :: Initialization
} deriving (CLASSES)
data Initialization = Initialization
{ initializationLocation :: Maybe (Vector CompressedWord)
, initializationRotation :: Maybe (Vector Int8)
} deriving (CLASSES)
data Vector value = Vector
{ vectorX :: value
, vectorY :: value
, vectorZ :: value
} deriving (CLASSES)
newtype UpdatedReplication = UpdatedReplication
{ updatedReplicationAttributes :: [Attribute]
} deriving (CLASSES)
data Attribute = Attribute
{ attributeId :: CompressedWord
, attributeValue :: AttributeValue
} deriving (CLASSES)
data AttributeValue
= AppliedDamageAttributeValue AppliedDamageAttribute
| BooleanAttributeValue BooleanAttribute
| ByteAttributeValue ByteAttribute
| CamSettingsAttributeValue CamSettingsAttribute
| ClubColorsAttributeValue ClubColorsAttribute
| DamageStateAttributeValue DamageStateAttribute
| DemolishAttributeValue DemolishAttribute
| EnumAttributeValue EnumAttribute
| ExplosionAttributeValue ExplosionAttribute
| FlaggedIntAttributeValue FlaggedIntAttribute
| FloatAttributeValue FloatAttribute
| GameModeAttributeValue GameModeAttribute
| IntAttributeValue IntAttribute
| LoadoutAttributeValue LoadoutAttribute
| LoadoutOnlineAttributeValue LoadoutOnlineAttribute
| LoadoutsAttributeValue LoadoutsAttribute
| LoadoutsOnlineAttributeValue LoadoutsOnlineAttribute
| LocationAttributeValue LocationAttribute
| MusicStingerAttributeValue MusicStingerAttribute
| PartyLeaderAttributeValue PartyLeaderAttribute
| PickupAttributeValue PickupAttribute
| PrivateMatchSettingsAttributeValue PrivateMatchSettingsAttribute
| QWordAttributeValue QWordAttribute
| ReservationAttributeValue ReservationAttribute
| RigidBodyStateAttributeValue RigidBodyStateAttribute
| StringAttributeValue StringAttribute
| TeamPaintAttributeValue TeamPaintAttribute
| UniqueIdAttributeValue UniqueIdAttribute
| WeldedInfoAttributeValue WeldedInfoAttribute
deriving (CLASSES)
data AppliedDamageAttribute = AppliedDamageAttribute
{ appliedDamageAttributeUnknown1 :: Word8
, appliedDamageAttributeLocation :: Vector CompressedWord
, appliedDamageAttributeUnknown3 :: Int32
, appliedDamageAttributeUnknown4 :: Int32
} deriving (CLASSES)
newtype BooleanAttribute = BooleanAttribute
{ booleanAttributeValue :: Bool
} deriving (CLASSES)
newtype ByteAttribute = ByteAttribute
{ byteAttributeValue :: Word8
} deriving (CLASSES)
data CamSettingsAttribute = CamSettingsAttribute
{ camSettingsAttributeFov :: Float
, camSettingsAttributeHeight :: Float
, camSettingsAttributeAngle :: Float
, camSettingsAttributeDistance :: Float
, camSettingsAttributeStiffness :: Float
, camSettingsAttributeSwivelSpeed :: Float
} deriving (CLASSES)
data ClubColorsAttribute = ClubColorsAttribute
{ clubColorsAttributeBlueFlag :: Bool
, clubColorsAttributeBlueColor :: Word8
, clubColorsAttributeOrangeFlag :: Bool
, clubColorsAttributeOrangeColor :: Word8
} deriving (CLASSES)
data DamageStateAttribute = DamageStateAttribute
{ damageStateAttributeUnknown1 :: Word8
, damageStateAttributeUnknown2 :: Bool
, damageStateAttributeUnknown3 :: Int32
, damageStateAttributeUnknown4 :: Vector CompressedWord
, damageStateAttributeUnknown5 :: Bool
, damageStateAttributeUnknown6 :: Bool
} deriving (CLASSES)
data DemolishAttribute = DemolishAttribute
{ demolishAttributeAttackerFlag :: Bool
, demolishAttributeAttackerActorId :: Word32
, demolishAttributeVictimFlag :: Bool
, demolishAttributeVictimActorId :: Word32
, demolishAttributeAttackerVelocity :: Vector CompressedWord
, demolishAttributeVictimVelocity :: Vector CompressedWord
} deriving (CLASSES)
newtype EnumAttribute = EnumAttribute
{ enumAttributeValue :: Word16
} deriving (CLASSES)
data ExplosionAttribute = ExplosionAttribute
{ explosionAttributeActorId :: Int32
, explosionAttributeLocation :: Vector CompressedWord
} deriving (CLASSES)
data FlaggedIntAttribute = FlaggedIntAttribute
{ flaggedIntAttributeFlag :: Bool
, flaggedIntAttributeInt :: Int32
} deriving (CLASSES)
newtype FloatAttribute = FloatAttribute
{ floatAttributeValue :: Float
} deriving (CLASSES)
data GameModeAttribute = GameModeAttribute
{ gameModeAttributeNumBits :: Int
, gameModeAttributeWord :: Word8
} deriving (CLASSES)
newtype IntAttribute = IntAttribute
{ intAttributeValue :: Int32
} deriving (CLASSES)
data LoadoutAttribute = LoadoutAttribute
{ loadoutAttributeVersion :: Word8
, loadoutAttributeBody :: Word32
, loadoutAttributeDecal :: Word32
, loadoutAttributeWheels :: Word32
, loadoutAttributeRocketTrail :: Word32
, loadoutAttributeAntenna :: Word32
, loadoutAttributeTopper :: Word32
, loadoutAttributeUnknown1 :: Word32
, loadoutAttributeUnknown2 :: Maybe Word32
} deriving (CLASSES)
newtype LoadoutOnlineAttribute = LoadoutOnlineAttribute
{ loadoutAttributeValue :: [[(Word32, CompressedWord)]]
} deriving (CLASSES)
data LoadoutsAttribute = LoadoutsAttribute
{ loadoutsAttributeBlue :: LoadoutAttribute
, loadoutsAttributeOrange :: LoadoutAttribute
} deriving (CLASSES)
data LoadoutsOnlineAttribute = LoadoutsOnlineAttribute
{ loadoutsOnlineAttributeBlue :: LoadoutOnlineAttribute
, loadoutsOnlineAttributeOrange :: LoadoutOnlineAttribute
, loadoutsOnlineAttributeUnknown1 :: Bool
, loadoutsOnlineAttributeUnknown2 :: Bool
} deriving (CLASSES)
newtype LocationAttribute = LocationAttribute
{ locationAttributeValue :: Vector CompressedWord
} deriving (CLASSES)
data MusicStingerAttribute = MusicStingerAttribute
{ musicStingerAttributeFlag :: Bool
, musicStingerAttributeCue :: Word32
, musicStingerAttributeTrigger :: Word8
} deriving (CLASSES)
data PartyLeaderAttribute = PartyLeaderAttribute
{ partyLeaderAttributeSystemId :: Word8
, partyLeaderAttributeId :: Maybe (RemoteId, Word8)
} deriving (CLASSES)
data RemoteId
= PlayStationId String [Word8]
| SplitscreenId Word32
| SteamId Word64
| XboxId Word64
deriving (CLASSES)
data PickupAttribute = PickupAttribute
{ pickupAttributeInstigatorId :: Maybe Word32
, pickupAttributePickedUp :: Bool
} deriving (CLASSES)
data PrivateMatchSettingsAttribute = PrivateMatchSettingsAttribute
{ privateMatchSettingsAttributeMutators :: String
, privateMatchSettingsAttributeJoinableBy :: Word32
, privateMatchSettingsAttributeMaxPlayers :: Word32
, privateMatchSettingsAttributeGameName :: String
, privateMatchSettingsAttributePassword :: String
, privateMatchSettingsAttributeFlag :: Bool
} deriving (CLASSES)
newtype QWordAttribute = QWordAttribute
{ qWordAttributeValue :: Word64
} deriving (CLASSES)
data ReservationAttribute = ReservationAttribute
{ reservationAttributeNumber :: CompressedWord
, reservationAttributeUniqueId :: UniqueIdAttribute
, reservationAttributeName :: Maybe String
, reservationAttributeUnknown1 :: Bool
, reservationAttributeUnknown2 :: Bool
, reservationAttributeUnknown3 :: Maybe Word8
} deriving (CLASSES)
data RigidBodyStateAttribute = RigidBodyStateAttribute
{ rigidBodyStateAttributeSleeping :: Bool
, rigidBodyStateAttributeLocation :: Vector CompressedWord
, rigidBodyStateAttributeRotation :: Vector CompressedWord
, rigidBodyStateAttributeLinearVelocity :: Maybe (Vector CompressedWord)
, rigidBodyStateAttributeAngularVelocity :: Maybe (Vector CompressedWord)
} deriving (CLASSES)
newtype StringAttribute = StringAttribute
{ stringAttributeValue :: String
} deriving (CLASSES)
data TeamPaintAttribute = TeamPaintAttribute
{ teamPaintAttributeTeam :: Word8
, teamPaintAttributePrimaryColor :: Word8
, teamPaintAttributeAccentColor :: Word8
, teamPaintAttributePrimaryFinish :: Word32
, teamPaintAttributeAccentFinish :: Word32
} deriving (CLASSES)
data UniqueIdAttribute = UniqueIdAttribute
{ uniqueIdAttributeSystemId :: Word8
, uniqueIdAttributeRemoteId :: RemoteId
, uniqueIdAttributeLocalId :: Word8
} deriving (CLASSES)
data WeldedInfoAttribute = WeldedInfoAttribute
{ weldedInfoAttributeActive :: Bool
, weldedInfoAttributeActorId :: Int32
, weldedInfoAttributeOffset :: Vector CompressedWord
, weldedInfoAttributeMass :: Float
, weldedInfoAttributeRotation :: Vector Int8
} deriving (CLASSES)
data DestroyedReplication = DestroyedReplication
{
} deriving (CLASSES)
data Message = Message
{ messageFrame :: Word32
, messageName :: String
, messageValue :: String
} deriving (CLASSES)
data Mark = Mark
{ markValue :: String
, markFrame :: Word32
} deriving (CLASSES)
data ClassMapping = ClassMapping
{ classMappingName :: String
, classMappingStreamId :: Word32
} deriving (CLASSES)
data Cache = Cache
{ cacheClassId :: Word32
, cacheParentCacheId :: Word32
, cacheCacheId :: Word32
, cacheAttributeMappings :: [AttributeMapping]
} deriving (CLASSES)
data AttributeMapping = AttributeMapping
{ attributeMappingObjectId :: Word32
, attributeMappingStreamId :: Word32
} deriving (CLASSES)
from ubuntu:17.04
run apt-get update
run apt-get install --assume-yes software-properties-common
run add-apt-repository ppa:hvr/ghc
run apt-get update
run apt-get install --assume-yes ghc-8.2.1
run apt-get install --assume-yes ghc-8.0.2
run apt-get install --assume-yes ghc-8.0.1
run apt-get install --assume-yes ghc-7.10.3
run apt-get install --assume-yes ghc-7.10.2
run apt-get install --assume-yes ghc-7.10.1
run apt-get install --assume-yes ghc-7.8.4
run apt-get install --assume-yes ghc-7.8.3
run apt-get install --assume-yes ghc-7.8.2
run apt-get install --assume-yes ghc-7.8.1
run apt-get install --assume-yes ghc-7.6.3
run apt-get install --assume-yes ghc-7.6.2
run apt-get install --assume-yes ghc-7.6.1
run apt-get install --assume-yes ghc-7.4.2
run apt-get install --assume-yes ghc-7.4.1
run apt-get install --assume-yes ghc-7.2.2
run apt-get install --assume-yes ghc-7.2.1
run apt-get install --assume-yes ghc-7.0.4
run apt-get install --assume-yes ghc-7.0.3
run apt-get install --assume-yes ghc-7.0.2
run apt-get install --assume-yes ghc-7.0.1
env PATH /opt/ghc/bin:$PATH
env LC_ALL C.UTF-8
run apt-get install --assume-yes cabal-install-2.0
env PATH /opt/cabal/bin:$PATH
run cabal-2.0 update
run cabal-2.0 install bench-1.0.5
env PATH /root/.cabal/bin:$PATH
workdir /root/project
copy Deriving.hs /root/project
volume /root/project/data
copy template.html /root/project
cmd bench \
--csv data/report.csv \
--json data/report.json \
--output data/report.html \
--raw data/report.raw \
--template ./template.html \
'ghc-8.2.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES= -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Data,Typeable -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Eq -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Eq,Ord -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Read -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Show -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Typeable -fforce-recomp Deriving.hs' \
'ghc-8.2.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-8.0.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-8.0.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.3 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.10.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.4 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.3 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.8.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.3 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.6.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.4.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.4.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.2.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.2.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.4 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.3 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.2 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
'ghc-7.0.1 -DCLASSES=Data,Eq,Ord,Read,Show,Typeable -fforce-recomp Deriving.hs' \
| tee data/report.txt
#!/usr/bin/env sh
set -o errexit -o xtrace
time docker build --tag deriving .
mkdir -p data
time docker run --interactive --rm --tty --volume "$(pwd)/data:/root/project/data" deriving
xdg-open data/report.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- from https://github.com/bos/criterion/blob/8a1d397dba3d863752da8f223dc4a3fc0b9cc798/templates/default.tpl -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>criterion report</title>
<script language="javascript" type="text/javascript">
{{{js-jquery}}}
</script>
<script language="javascript" type="text/javascript">
{{{js-flot}}}
</script>
<script language="javascript" type="text/javascript">
(function ($) {
$.zip = function(a,b) {
var x = Math.min(a.length,b.length);
var c = new Array(x);
for (var i = 0; i < x; i++)
c[i] = [a[i],b[i]];
return c;
};
$.mean = function(ary) {
var m = 0, i = 0;
while (i < ary.length) {
var j = i++;
m += (ary[j] - m) / i;
}
return m;
};
$.timeUnits = function(secs) {
if (secs < 0) return $.timeUnits(-secs);
else if (secs >= 1e9) return [1e-9, "Gs"];
else if (secs >= 1e6) return [1e-6, "Ms"];
else if (secs >= 1) return [1, "s"];
else if (secs >= 1e-3) return [1e3, "ms"];
else if (secs >= 1e-6) return [1e6, "\u03bcs"];
else if (secs >= 1e-9) return [1e9, "ns"];
else if (secs >= 1e-12) return [1e12, "ps"];
return [1, "s"];
};
$.scaleTimes = function(ary) {
var s = $.timeUnits($.mean(ary));
return [$.scaleBy(s[0], ary), s[0]];
};
$.prepareTime = function(secs) {
var units = $.timeUnits(secs);
var scaled = secs * units[0];
var s = scaled.toPrecision(3);
var t = scaled.toString();
return [t.length < s.length ? t : s, units[1]];
};
$.scaleBy = function(x, ary) {
var nary = new Array(ary.length);
for (var i = 0; i < ary.length; i++)
nary[i] = ary[i] * x;
return nary;
};
$.renderTime = function(secs) {
var x = $.prepareTime(secs);
return x[0] + ' ' + x[1];
};
$.unitFormatter = function(scale) {
var labelname;
return function(secs,axis) {
var x = $.prepareTime(secs / scale);
if (labelname === x[1])
return x[0];
else {
labelname = x[1];
return x[0] + ' ' + x[1];
}
};
};
$.addTooltip = function(name, renderText) {
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': '#fee',
opacity: 0.80
}).appendTo("body").fadeIn(200);
};
var pp = null;
$(name).bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if (item) {
if (pp != item.dataIndex) {
pp = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0],
y = item.datapoint[1];
showTooltip(item.pageX, item.pageY, renderText(x,y));
}
}
else {
$("#tooltip").remove();
pp = null;
}
});
};
})(jQuery);
</script>
<style type="text/css">
html, body {
height: 100%;
margin: 0;
}
#wrap {
min-height: 100%;
}
#main {
overflow: auto;
padding-bottom: 180px; /* must be same height as the footer */
}
#footer {
position: relative;
margin-top: -180px; /* negative value of footer height */
height: 180px;
clear: both;
background: #888;
margin: 40px 0 0;
color: white;
font-size: larger;
font-weight: 300;
}
body:before {
/* Opera fix */
content: "";
height: 100%;
float: left;
width: 0;
margin-top: -32767px;
}
body {
font: 14px Helvetica Neue;
text-rendering: optimizeLegibility;
margin-top: 1em;
}
a:link {
color: steelblue;
text-decoration: none;
}
a:visited {
color: #4a743b;
text-decoration: none;
}
#footer a {
color: white;
text-decoration: underline;
}
.hover {
color: steelblue;
text-decoration: none;
}
.body {
width: 960px;
margin: auto;
}
.footfirst {
position: relative;
top: 30px;
}
th {
font-weight: 500;
opacity: 0.8;
}
th.cibound {
opacity: 0.4;
}
.confinterval {
opacity: 0.5;
}
h1 {
font-size: 36px;
font-weight: 300;
margin-bottom: .3em;
}
h2 {
font-size: 30px;
font-weight: 300;
margin-bottom: .3em;
}
.meanlegend {
color: #404040;
background-color: #ffffff;
opacity: 0.6;
font-size: smaller;
}
</style>
<!--[if !IE 7]>
<style type="text/css">
#wrap {display:table;height:100%}
</style>
<![endif]-->
</head>
<body>
<div id="wrap">
<div id="main" class="body">
<h1>criterion performance measurements</h1>
<h2>overview</h2>
<p><a href="#grokularation">want to understand this report?</a></p>
<div id="overview" class="ovchart" style="width:900px;height:100px;"></div>
{{#report}}
<h2><a name="b{{number}}">{{name}}</a></h2>
<table width="100%">
<tbody>
<tr>
<td><div id="kde{{number}}" class="kdechart"
style="width:450px;height:278px;"></div></td>
<td><div id="time{{number}}" class="timechart"
style="width:450px;height:278px;"></div></td>
<!--
<td><div id="cycle{{number}}" class="cyclechart"
style="width:300px;height:278px;"></div></td>
-->
</tr>
</tbody>
</table>
<table>
<thead class="analysis">
<th></th>
<th class="cibound"
title="{{anMean.estConfidenceLevel}} confidence level">lower bound</th>
<th>estimate</th>
<th class="cibound"
title="{{anMean.estConfidenceLevel}} confidence level">upper bound</th>
</thead>
<tbody>
<tr>
<td>OLS regression</td>
<td><span class="confinterval olstimelb{{number}}">xxx</span></td>
<td><span class="olstimept{{number}}">xxx</span></td>
<td><span class="confinterval olstimeub{{number}}">xxx</span></td>
</tr>
<tr>
<td>R&#xb2; goodness-of-fit</td>
<td><span class="confinterval olsr2lb{{number}}">xxx</span></td>
<td><span class="olsr2pt{{number}}">xxx</span></td>
<td><span class="confinterval olsr2ub{{number}}">xxx</span></td>
</tr>
<tr>
<td>Mean execution time</td>
<td><span class="confinterval citime">{{anMean.estError.confIntLDX}}</span></td>
<td><span class="time">{{anMean.estPoint}}</span></td>
<td><span class="confinterval citime">{{anMean.estError.confIntUDX}}</span></td>
</tr>
<tr>
<td>Standard deviation</td>
<td><span class="confinterval citime">{{anStdDev.estError.confIntLDX}}</span></td>
<td><span class="time">{{anStdDev.estPoint}}</span></td>
<td><span class="confinterval citime">{{anStdDev.estError.confIntUDX}}</span></td>
</tr>
</tbody>
</table>
<span class="outliers">
<p>Outlying measurements have {{anOutlierVar.ovDesc}}
(<span class="percent">{{anOutlierVar.ovFraction}}</span>%)
effect on estimated standard deviation.</p>
</span>
{{/report}}
<h2><a name="grokularation">understanding this report</a></h2>
<p>In this report, each function benchmarked by criterion is assigned
a section of its own. The charts in each section are active; if
you hover your mouse over data points and annotations, you will see
more details.</p>
<ul>
<li>The chart on the left is a
<a href="http://en.wikipedia.org/wiki/Kernel_density_estimation">kernel
density estimate</a> (also known as a KDE) of time
measurements. This graphs the probability of any given time
measurement occurring. A spike indicates that a measurement of a
particular time occurred; its height indicates how often that
measurement was repeated.</li>
<li>The chart on the right is the raw data from which the kernel
density estimate is built. The <i>x</i> axis indicates the
number of loop iterations, while the <i>y</i> axis shows measured
execution time for the given number of loop iterations. The
line behind the values is the linear regression prediction of
execution time for a given number of iterations. Ideally, all
measurements will be on (or very near) this line.</li>
</ul>
<p>Under the charts is a small table.
The first two rows are the results of a linear regression run
on the measurements displayed in the right-hand chart.</p>
<ul>
<li><i>OLS regression</i> indicates the
time estimated for a single loop iteration using an ordinary
least-squares regression model. This number is more accurate
than the <i>mean</i> estimate below it, as it more effectively
eliminates measurement overhead and other constant factors.</li>
<li><i>R&#xb2; goodness-of-fit</i> is a measure of how
accurately the linear regression model fits the observed
measurements. If the measurements are not too noisy, R&#xb2;
should lie between 0.99 and 1, indicating an excellent fit. If
the number is below 0.99, something is confounding the accuracy
of the linear model.</li>
<li><i>Mean execution time</i> and <i>standard deviation</i> are
statistics calculated from execution time
divided by number of iterations.</li>
</ul>
<p>We use a statistical technique called
the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a>
to provide confidence intervals on our estimates. The
bootstrap-derived upper and lower bounds on estimates let you see
how accurate we believe those estimates to be. (Hover the mouse
over the table headers to see the confidence levels.)</p>
<p>A noisy benchmarking environment can cause some or many
measurements to fall far from the mean. These outlying
measurements can have a significant inflationary effect on the
estimate of the standard deviation. We calculate and display an
estimate of the extent to which the standard deviation has been
inflated by outliers.</p>
<script type="text/javascript">
$(function () {
function mangulate(rpt) {
var measured = function(key) {
var idx = rpt.reportKeys.indexOf(key);
return rpt.reportMeasured.map(function(r) { return r[idx]; });
};
var number = rpt.reportNumber;
var name = rpt.reportName;
var mean = rpt.reportAnalysis.anMean.estPoint;
var iters = measured("iters");
var times = measured("time");
var kdetimes = rpt.reportKDEs[0].kdeValues;
var kdepdf = rpt.reportKDEs[0].kdePDF;
var meanSecs = mean;
var units = $.timeUnits(mean);
var rgrs = rpt.reportAnalysis.anRegress[0];
var scale = units[0];
var olsTime = rgrs.regCoeffs.iters;
$(".olstimept" + number).text(function() {
return $.renderTime(olsTime.estPoint);
});
$(".olstimelb" + number).text(function() {
return $.renderTime(olsTime.estError.confIntLDX);
});
$(".olstimeub" + number).text(function() {
return $.renderTime(olsTime.estError.confIntUDX);
});
$(".olsr2pt" + number).text(function() {
return rgrs.regRSquare.estPoint.toFixed(3);
});
$(".olsr2lb" + number).text(function() {
return rgrs.regRSquare.estError.confIntLDX.toFixed(3);
});
$(".olsr2ub" + number).text(function() {
return rgrs.regRSquare.estError.confIntUDX.toFixed(3);
});
mean *= scale;
kdetimes = $.scaleBy(scale, kdetimes);
var kq = $("#kde" + number);
var k = $.plot(kq,
[{ label: name + " time densities",
data: $.zip(kdetimes, kdepdf),
}],
{ xaxis: { tickFormatter: $.unitFormatter(scale) },
yaxis: { ticks: false },
grid: { borderColor: "#777",
hoverable: true, markings: [ { color: '#6fd3fb',
lineWidth: 1.5, xaxis: { from: mean, to: mean } } ] },
});
var o = k.pointOffset({ x: mean, y: 0});
kq.append('<div class="meanlegend" title="' + $.renderTime(meanSecs) +
'" style="position:absolute;left:' + (o.left + 4) +
'px;bottom:139px;">mean</div>');
$.addTooltip("#kde" + number,
function(secs) { return $.renderTime(secs / scale); });
var timepairs = new Array(times.length);
var lastiter = iters[iters.length-1];
var olspairs = [[0,0], [lastiter, lastiter * scale * olsTime.estPoint]];
for (var i = 0; i < times.length; i++)
timepairs[i] = [iters[i],times[i]*scale];
iterFormatter = function() {
var denom = 0;
return function(iters) {
if (iters == 0)
return '';
if (denom > 0)
return (iters / denom).toFixed();
var power;
if (iters >= 1e9) {
denom = '1e9'; power = '&#x2079;';
}
if (iters >= 1e6) {
denom = '1e6'; power = '&#x2076;';
}
else if (iters >= 1e3) {
denom = '1e3'; power = '&#xb3;';
}
else denom = 1;
if (denom > 1) {
iters = (iters / denom).toFixed();
iters += '&times;10' + power + ' iters';
} else {
iters += ' iters';
}
return iters;
};
};
$.plot($("#time" + number),
[{ label: "regression", data: olspairs,
lines: { show: true } },
{ label: name + " times", data: timepairs,
points: { show: true } }],
{ grid: { borderColor: "#777", hoverable: true },
xaxis: { tickFormatter: iterFormatter() },
yaxis: { tickFormatter: $.unitFormatter(scale) } });
$.addTooltip("#time" + number,
function(iters,secs) {
return ($.renderTime(secs / scale) + ' / ' +
iters.toLocaleString() + ' iters');
});
if (0) {
var cyclepairs = new Array(cycles.length);
for (var i = 0; i < cycles.length; i++)
cyclepairs[i] = [cycles[i],i];
$.plot($("#cycle" + number),
[{ label: name + " cycles",
data: cyclepairs }],
{ points: { show: true },
grid: { borderColor: "#777", hoverable: true },
xaxis: { tickFormatter:
function(cycles,axis) { return cycles + ' cycles'; }},
yaxis: { ticks: false },
});
$.addTooltip("#cycles" + number, function(x,y) { return x + ' cycles'; });
}
};
var reports = {{{json}}};
reports.map(mangulate);
var benches = [{{#report}}"{{name}}",{{/report}}];
var ylabels = [{{#report}}[-{{number}},'<a href="#b{{number}}">{{name}}</a>'],{{/report}}];
var means = $.scaleTimes([{{#report}}{{anMean.estPoint}},{{/report}}]);
var xs = [];
var prev = null;
for (var i = 0; i < means[0].length; i++) {
var name = benches[i].split(/\//);
name.pop();
name = name.join('/');
if (name != prev) {
xs.push({ label: name, data: [[means[0][i], -i]]});
prev = name;
}
else
xs[xs.length-1].data.push([means[0][i],-i]);
}
var oq = $("#overview");
o = $.plot(oq, xs, { bars: { show: true, horizontal: true,
barWidth: 0.75, align: "center" },
grid: { borderColor: "#777", hoverable: true },
legend: { show: xs.length > 1 },
xaxis: { max: Math.max.apply(undefined,means[0]) * 1.02 },
yaxis: { ticks: ylabels, tickColor: '#ffffff' } });
if (benches.length > 3)
o.getPlaceholder().height(28*benches.length);
o.resize();
o.setupGrid();
o.draw();
$.addTooltip("#overview", function(x,y) { return $.renderTime(x / means[1]); });
});
$(document).ready(function () {
$(".time").text(function(_, text) {
return $.renderTime(text);
});
$(".citime").text(function(_, text) {
return $.renderTime(text);
});
$(".percent").text(function(_, text) {
return (text*100).toFixed(1);
});
});
</script>
</div>
</div>
<div id="footer">
<div class="body">
<div class="footfirst">
<h2>colophon</h2>
<p>This report was created using the
<a href="http://hackage.haskell.org/package/criterion">criterion</a>
benchmark execution and performance analysis tool.</p>
<p>Criterion is developed and maintained
by <a href="http://www.serpentine.com/blog/">Bryan O'Sullivan</a>.</p>
</div>
</div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment