packages feed

gipeda 0.3.2.2 → 0.3.3.0

raw patch · 4 files changed

+173/−90 lines, 4 filesdep ~aeson

Dependency ranges changed: aeson

Files

gipeda.cabal view
@@ -1,5 +1,5 @@ name:                gipeda-version:             0.3.2.2+version:             0.3.3.0 category:            Development synopsis:            Git Performance Dashboard description:@@ -76,7 +76,7 @@       vector               >= 0.10  && <0.12,       cassava              >= 0.4   && <0.5,       yaml                 >= 0.8   && <0.9,-      aeson                >= 0.7   && <1.1,+      aeson                >= 0.7   && <1.2,       scientific           >= 0.3   && <0.4,       gitlib               >= 3.1.0.2 && <3.2,       gitlib-libgit2,
site/js/gipeda.js view
@@ -47,7 +47,15 @@         { regex: /^revision\/([a-f0-9]+)$/,           viewData: function (match) { return { hash: match[1] }; },           download: function () {-            return ['out/benchNames.json','out/reports/' + viewData.hash + '.json'];+            todo = ['out/benchNames.json','out/reports/' + viewData.hash + '.json'];+            if (data && data.revisions) {+                var rev = data.revisions[viewData.hash];+                if (rev && rev.summary && rev.summary.parents) {+                    var parentHash = rev.summary.parents[0];+                    todo.push('out/reports/' + parentHash + '.json');+                }+            }+            return todo;           },           url: function (hash) { return "revision/" + hash; },         },@@ -105,13 +113,15 @@     viewChanged.dispatch(); } -viewChanged.add(function () {+function load_missing_data() {     if (routes[view].download) {         d = routes[view].download;-        if ($.isFunction(d)) {d = d()}-        d.forEach(function (url) { getJSON(url) });+        if ($.isFunction(d)) {d = d(); }+        d.forEach(function (url) { getJSON(url); });     }-});+}+viewChanged.add(load_missing_data);+dataChanged.add(load_missing_data);  function handleHashChange(newHash) {     parseRoute(newHash);@@ -343,7 +353,7 @@         if (benchmark_name_matches(s.match, name)) {             $.extend(benchSettings, s);         }-    })+    });      return benchSettings; }@@ -351,12 +361,12 @@  // The following logic should be kept in sync with toResult in ReportTypes.hs function compareResults (res1, res2) {-    if (!res1 && !res2) { return };+    if (!res1 && !res2) { return; } -    name = res1? res1.name : res2.name;-    s = setting_for(name);+    var name = res1? res1.name : res2.name;+    var s = setting_for(name); -    res = {+    var res = {         name: name,         previous:    res1 ? res1.value : null,         value:       res2 ? res2.value : null,@@ -368,9 +378,9 @@      if (res1 && res2){         if (s.type == "integral" || s.type == "float"){-            if (res1.value == 0 && res2.value == 0) {+            if (res1.value === 0 && res2.value === 0) {                 res.change = "=";-            } else if (res1.value == 0) {+            } else if (res1.value === 0) {                 res.change = "+  ∞";                 res.changeType = "Improvement";             } else {@@ -418,26 +428,73 @@     return res; } +// A variant of compareResults, for when there is nothing to compare.+function singleResult (res) {+    if (!res) { return; }+    var name = res.name;+    var s = setting_for(name);++    return  {+        name: name,+        previous:    null,+        value:       res.value,+        unit:        s.unit,+        important:   s.important,+        changeType: "Boring",+        change:     "",+    };+}+ // Some views require the data to be prepared in ways that are  // too complicated for the template, so lets do it here.-dataViewPrepare = {-  'revision': function (data, viewData) {-    if (!data.benchGroups || !data.revisions) return {};-    var hash = viewData.hash;-    var rev = data.revisions[hash];-    if (!rev) return {};-    if (!rev.benchResults) return {}; -    var groups = data.benchGroups.map(function (group) {+// revision and compare actually share a lot of logic, the difference is only+// where the starting commit is from+function calculate_groups(rev1, rev2) {+    if (!rev2) return {};+    if (!rev2.benchResults) return {};++    return data.benchGroups.map(function (group) {       var benchmarks = group.groupMembers.map(function (bn) {-	return rev.benchResults[bn]-      }).filter(function (br) {return br});+        var r2 = rev2.benchResults[bn];+        if (rev1 && rev1.benchResults) {+            var r1 = rev1.benchResults[bn];+            return compareResults(r1,r2);+        } else {+            return singleResult(r2);+        }+      }).filter(function (br) {return br;});       return { 	groupName: group.groupName || "Benchmarks", 	benchResults: benchmarks, 	groupStats: groupStats(benchmarks),       };     });+}++dataViewPrepare = {+  'revision': function (data, viewData) {+    if (!data.benchGroups || !data.revisions) return {};+    var hash = viewData.hash;+    var rev = data.revisions[hash];++    if (!rev) return {};+    if (!rev.benchResults) return {};++    var groups;+    if (rev.summary.parents) {+        var parentHash = rev.summary.parents[0];+        var parentRev  = data.revisions[parentHash];++        if (parentRev) {+            groups = calculate_groups(parentRev, rev);+        }+    }+    // Fallback (no parent, or parent not loaded yet)+    if (!groups) {+        groups = calculate_groups(null, rev);+    }+     return {       rev : rev,       groups : groups,@@ -449,30 +506,13 @@     var hash2 = viewData.hash2;     var rev1 = data.revisions[hash1];     var rev2 = data.revisions[hash2];-    if (!rev1) return {};-    if (!rev1.benchResults) return {};-    if (!rev2) return {};-    if (!rev2.benchResults) return {};--    var groups = data.benchGroups.map(function (group) {-      var benchmarks = group.groupMembers.map(function (bn) {-	var r1 = rev1.benchResults[bn];-	var r2 = rev2.benchResults[bn];-	return compareResults(r1,r2);-      }).filter(function (br) {return br});-      return {-	groupName: group.groupName || "Benchmarks",-	benchResults: benchmarks,-	groupStats: groupStats(benchmarks),-      };-    });     return {       rev1 : rev1,       rev2 : rev2,-      groups : groups,+      groups : calculate_groups(rev1, rev2),     };   },-}+};  function remember_from_to() {     settings.compare.from = $('#compare-from').data('rev');
src/GraphReport.hs view
@@ -18,24 +18,51 @@ graphReportMain :: [String] -> IO () graphReportMain (bench:revs) = do     settings <- S.readSettings "gipeda.yaml"+    let s = S.benchSettings settings bench -    g <- forM revs $ \rev -> do-        json <- BS.readFile (reportOf rev)-        rep <- case eitherDecode json of-            Left e -> fail e-            Right rep -> return rep-        case M.lookup bench (benchResults (rep !!! "revisions" !!! rev)) of+    g <- forM (withPrev revs) $ \(rev, prevM) -> do+        report <- readReport rev++        case M.lookup bench (benchResults report) of             Nothing -> return Nothing-            Just result -> return $ Just $ T.pack rev .= object+            Just result -> do+                changeType <- case prevM of+                    Nothing -> return Boring+                    Just prev -> do+                        prevReport <- readReport prev+                        case M.lookup bench (benchResults prevReport) of+                            Nothing -> return Boring+                            Just prevResult ->+                                let comp = makeComparison s bench (value result) (Just (value prevResult))+                                in return $ changeType comp++                return $ Just $ T.pack rev .= object                         [ "benchResults" .= object-                            [ T.pack bench .= benchResultToGraphPoint result ]+                            [ T.pack bench .= GraphPoint+                                { gpValue = value result+                                , gpChangeType = changeType+                                }+                            ]                         ]     let doc = object                 [ "revisions" .= object (catMaybes g)                 , "benchmarkSettings" .= object-                    [ T.pack bench .= toJSON (S.benchSettings settings bench) ]+                    [ T.pack bench .= toJSON s ]                 ]      BS.putStr (encode doc)-  where-   m !!! k =  m M.! T.pack k++readReport :: Hash -> IO RevReport+readReport hash = do+    json <- BS.readFile (reportOf hash)+    case eitherDecode json of+        Left e    -> fail e+        Right rep -> return $ rep !!! "revisions" !!! hash++(!!!) :: M.Map T.Text a -> String -> a+m !!! k =  m M.! T.pack k++withPrev :: [a] -> [(a, Maybe a)]+withPrev (x:y:ys) = (x, Just y) : withPrev (y:ys)+withPrev [x]      = [(x, Nothing)]+withPrev []       = []
src/ReportTypes.hs view
@@ -63,12 +63,18 @@             SummaryStats (a + a') (b + b') (c + c') -} +data Status = Built | Failed | Waiting+ deriving (Show, Generic)+instance ToJSON Status+instance FromJSON Status+ data Summary = Summary     { hash :: Hash     , gitDate :: Integer     , gitSubject :: String     , stats :: SummaryStats-    , parents :: [String]+    , parents :: [Hash]+--    , status :: Status     }  deriving (Generic) instance ToJSON Summary@@ -111,9 +117,6 @@ data BenchResult = BenchResult     { name :: String     , value :: BenchValue-    , previous :: Maybe BenchValue-    , change :: String-    , changeType :: ChangeType     , unit :: String     , important :: Bool     }@@ -126,7 +129,17 @@ instance FromJSON BenchResult where     parseJSON = genericParseJSON defaultOptions +data BenchComparison = BenchComparison+    { changeName :: String+    , change :: String+    , changeType :: ChangeType+    , changeImportant :: Bool+    }+ -- A smaller BenchResult+-- (This is a hack: BenchResult no longer carries a changeType. But it is convenient to+-- have that in the graph report, for the tallying for the graph summary. But all not very+-- satisfactory.) data GraphPoint = GraphPoint     { gpValue :: BenchValue     , gpChangeType :: ChangeType@@ -143,11 +156,6 @@ graphPointOptions = defaultOptions { fieldLabelModifier = fixup }   where fixup ('g':'p':c:cs) = toLower c : cs -benchResultToGraphPoint (BenchResult {..}) = GraphPoint-    { gpValue = value-    , gpChangeType = changeType-    }- invertChangeType :: ChangeType -> ChangeType invertChangeType Improvement = Regression invertChangeType Boring = Boring@@ -200,17 +208,22 @@ -- even if the user did not set the numberType correctly: explain s                                     v1     v2     = explainFloat s (toFloat v1) (toFloat v2) -toResult :: S.BenchSettings -> String -> BenchValue -> Maybe BenchValue -> BenchResult-toResult s name value prev = BenchResult-    { name = name-    , value = value-    , previous = prev-    , change = change-    , changeType = changeType-    , unit = S.unit s+toResult :: S.BenchSettings -> String -> BenchValue -> BenchResult+toResult s name value = BenchResult+    { name      = name+    , value     = value+    , unit      = S.unit s     , important = S.important s     }-  where ++makeComparison :: S.BenchSettings -> String -> BenchValue -> Maybe BenchValue -> BenchComparison+makeComparison s name value prev = BenchComparison+    { changeName      = name+    , change          = change+    , changeType      = changeType+    , changeImportant = S.important s+    }+  where     (change, changeType') =         case prev of             Just p -> explain s p value@@ -218,22 +231,20 @@     changeType | S.smallerIsBetter s = invertChangeType changeType'                | otherwise           =                  changeType' -toSummaryStats :: [BenchResult] -> SummaryStats-toSummaryStats res = SummaryStats-    { totalCount = length res+toSummaryStats :: [BenchComparison] -> SummaryStats+toSummaryStats comps = SummaryStats+    { totalCount = length comps     , improvementCount = length-        [ ()-        | BenchResult { changeType = Improvement, important = True } <- res-        ]+        [ () | comp <- importantComps , changeType comp == Improvement ]     , regressionCount =  length-        [ ()-        | BenchResult { changeType = Regression, important = True } <- res-        ]+        [ () | comp <- importantComps , changeType comp == Regression ]     , summaryDesc = andMore 5-        [ name r ++ ": " ++ change r-        | r <- res, important r, changeType r `elem` [Improvement, Regression]+        [ changeName comp ++ ": " ++ change comp+        | comp <- importantComps+        , changeType comp `elem` [Improvement, Regression]         ]     }+  where importantComps = filter changeImportant comps  andMore :: Int -> [String] -> String andMore _ [] = "–"@@ -262,12 +273,12 @@ createBranchReport settings this other thisM otherM commitCount = BranchReport     { branchHash = this     , mergeBaseHash = other-    , branchStats = toSummaryStats $ M.elems results+    , branchStats = toSummaryStats comparisons     , commitCount = commitCount     }   where-    results = M.fromList-        [ (name, toResult s name value (M.lookup name otherM))+    comparisons =+        [ makeComparison s name value (M.lookup name otherM)         | (name, value) <- M.toAscList thisM         , let s = S.benchSettings settings name         ]@@ -277,11 +288,11 @@     ResultMap -> ResultMap ->     String -> String -> Integer ->     RevReport-createReport settings this parents thisM parentM log subject date = RevReport +createReport settings this parents thisM parentM log subject date = RevReport     { summary = Summary         { hash = this         , parents = parents-        , stats = toSummaryStats $ M.elems results+        , stats = toSummaryStats comparisons         , gitSubject = subject         , gitDate = date         }@@ -291,10 +302,15 @@     }   where     results = M.fromList-        [ (name, toResult s name value (M.lookup name parentM))+        [ (name, toResult s name value)         | (name, value) <- M.toAscList thisM         , let s = S.benchSettings settings name         ]+    comparisons =+        [ makeComparison s name value (M.lookup name parentM)+        | (name, value) <- M.toAscList thisM+        , let s = S.benchSettings settings name+        ]  summarize :: RevReport -> Summary-summarize (RevReport {..}) =  summary +summarize (RevReport {..}) = summary