/** * InsertChart adds a chart for the given $metric, with the given $label, to * global $chartData, and outputs the HTML container elements for the chart. * * @param string $metric Metric to add * @param string $label Label corresponding to metric */ function InsertChart($metric, $label) { global $chartData; global $num_runs; // @var integer Number of runs global $views; global $colors; global $light_colors; global $median_metric; global $pagesData; global $testsInfo; global $testsId; global $testsLabel; global $median_value; global $median_run; global $statControl; $num_runs = max(array_map("numRunsFromTestInfo", $testsInfo)); // Write HTML for chart $div = "{$metric}Chart"; echo "<h2 id=\"{$metric}\">" . htmlspecialchars($label) . "</h2>"; if (!$testsInfo) { return; } $chartColumns = array(ChartColumn::runs($num_runs)); $compareTable = array(); $view_index = 0; // For each view (first / repeat) that we want to show foreach ($views as $cached) { $statValues = array(); $statLabels = array(); // For each run in that view foreach ($pagesData as $key => $pageData) { // Construct label from those descriptive attributes that are not // common to all variants. $labels = array(); if (count($pagesData) > 1) { $labels[] = $testsLabel[$key]; } if (count($views) > 1) { $labels[] = $cached == '1' ? 'Repeat View' : 'First View'; } // Prepare Chart object and add to $chartData for later chart construction. // If $view_index is greater than the number of colors, we will pass NULL // as a color, which will lead to GViz choosing a color. $chartColumnsAdd = ChartColumn::dataMedianColumns($pageData, $cached, $metric, $median_metric, $colors[$view_index], $light_colors[$view_index], $labels, $num_runs, $median_run, $median_value); $chartColumns = array_merge($chartColumns, $chartColumnsAdd); $view_index++; // If doing a statistical comparison, prepare raw values and labels. if ($statControl !== 'NOSTAT' && count($pagesData) >= 1) { $statValues[] = values($pageData, $cached, $metric, true); $statLabels[] = implode(" ", $labels); } } if ($statControl !== 'NOSTAT' && count($pagesData) >= 1) { // First populate compareFrom for statistical control, if it has values if (count($statValues[$statControl]) > 0) { $statDiv = "{$metric}Stat{$cached}"; $compareFrom = array(); $confData = ConfData::fromArr($statLabels[$statControl], $statValues[$statControl]); $compareFrom[$statControl] = new CompareFrom($confData, NULL, NULL); foreach ($pagesData as $key => $pageData) { // Skip the statistical control (we already handled it) if ($key == $statControl) { continue; } // Skip runs with missing values for the statistic. if (count($statValues[$key]) == 0) { continue; } // Populate compareFrom for $key $confData = ConfData::fromArr($statLabels[$key], $statValues[$key]); $pValue = \PHPStats\StatisticalTests::twoSampleTTest($statValues[$statControl], $statValues[$key]); $diff = $confData->mean - $compareFrom[$statControl]->confData->mean; // Derive 2-tailed p-value from 1-tailed p-view returned by twoSampleTTest. $pValue = $diff > 0 ? 2 * $pValue : 2 * (1 - $pValue); $compareFrom[$key] = new CompareFrom($confData, $diff, $pValue); } $compareTable[] = new CompareTable($statDiv, $compareFrom); echo "<div id=\"{$statDiv}\"></div>\n"; } } } $chart = new Chart($div, $chartColumns, $compareTable); $chartData[$metric] = $chart; echo "<div id=\"{$div}\" class=\"chart\"></div>\n"; }
/** * InsertChart adds a chart for the given $metric, with the given $label, to * global $chartData, and outputs the HTML container elements for the chart. * * @param string $metric Metric to add * @param string $label Label corresponding to metric */ function InsertChart($metric, $label) { global $chartData; global $num_runs; // @var integer Number of runs global $views; global $colors; global $light_colors; global $median_metric; global $pagesData; global $testsInfo; global $testsId; global $testsLabel; global $median_value; global $median_run; global $statControl; $num_runs = max(array_map("numRunsFromTestInfo", $testsInfo)); // Write HTML for chart $div = "{$metric}Chart"; echo "<h2 id=\"{$metric}\">" . htmlspecialchars($label) . "</h2>"; if (!$testsInfo) { return; } $chartColumns = array(ChartColumn::runs($num_runs)); $compareTable = array(); $view_index = 0; if (count($pagesData) == 1 && $num_runs >= 3) { echo '<div class="chartStats"><table class="pretty">'; echo '<tr><td></td><th>Mean</th><th>Median</th><th>p25</th><th>p75</th><th>p75-p25</th><th>StdDev</th><th>CV</th></tr>'; foreach ($views as $cached) { $pageData = reset($pagesData); echo '<tr>'; $label = $cached == '1' ? 'Repeat View' : 'First View'; echo "<th style=\"text-align: right;\">{$label}</th>"; $values = values($pageData, $cached, $metric, true); sort($values, SORT_NUMERIC); $sum = array_sum($values); $count = count($values); $mean = number_format($sum / $count, 3, '.', ''); echo "<td>{$mean}</td>"; $median = $values[intval($count / 2)]; echo "<td>{$median}</td>"; $p25 = $values[intval($count * 0.25)]; echo "<td>{$p25}</td>"; $p75 = $values[intval($count * 0.75)]; echo "<td>{$p75}</td>"; echo "<td>" . ($p75 - $p25) . "</td>"; $sqsum = 0; foreach ($values as $value) { $sqsum += pow($value - $mean, 2); } $stddev = number_format(sqrt($sqsum / $count), 3, '.', ''); echo "<td>{$stddev}</td>"; echo "<td>" . number_format($stddev / $mean * 100, 3, '.', '') . "%</td>"; echo '</tr>'; } echo '</table></div>'; } // For each view (first / repeat) that we want to show foreach ($views as $cached) { $statValues = array(); $statLabels = array(); // For each run in that view foreach ($pagesData as $key => $pageData) { // Construct label from those descriptive attributes that are not // common to all variants. $labels = array(); if (count($pagesData) > 1) { $labels[] = $testsLabel[$key]; } if (count($views) > 1) { $labels[] = $cached == '1' ? 'Repeat View' : 'First View'; } // Prepare Chart object and add to $chartData for later chart construction. // If $view_index is greater than the number of colors, we will pass NULL // as a color, which will lead to GViz choosing a color. $chartColumnsAdd = ChartColumn::dataMedianColumns($pageData, $cached, $metric, $median_metric, $colors[$view_index], $light_colors[$view_index], $labels, $num_runs, $median_run, $median_value); $chartColumns = array_merge($chartColumns, $chartColumnsAdd); $view_index++; // If doing a statistical comparison, prepare raw values and labels. if ($statControl !== 'NOSTAT' && count($pagesData) >= 1) { $statValues[] = values($pageData, $cached, $metric, true); $statLabels[] = implode(" ", $labels); } } if (is_file('lib/PHPStats/PHPStats.phar') && $statControl !== 'NOSTAT' && count($pagesData) >= 1) { require_once 'lib/PHPStats/PHPStats.phar'; require_once 'stat.inc'; // First populate compareFrom for statistical control, if it has values if (count($statValues[$statControl]) > 0) { $statDiv = "{$metric}Stat{$cached}"; $compareFrom = array(); $confData = ConfData::fromArr($statLabels[$statControl], $statValues[$statControl]); $compareFrom[$statControl] = new CompareFrom($confData, NULL, NULL); foreach ($pagesData as $key => $pageData) { // Skip the statistical control (we already handled it) if ($key == $statControl) { continue; } // Skip runs with missing values for the statistic. if (count($statValues[$key]) == 0) { continue; } // Populate compareFrom for $key $confData = ConfData::fromArr($statLabels[$key], $statValues[$key]); $pValue = \PHPStats\StatisticalTests::twoSampleTTest($statValues[$statControl], $statValues[$key]); $diff = $confData->mean - $compareFrom[$statControl]->confData->mean; // Derive 2-tailed p-value from 1-tailed p-view returned by twoSampleTTest. $pValue = $diff > 0 ? 2 * $pValue : 2 * (1 - $pValue); $compareFrom[$key] = new CompareFrom($confData, $diff, $pValue); } $compareTable[] = new CompareTable($statDiv, $compareFrom); echo "<div id=\"{$statDiv}\"></div>\n"; } } } $chart = new Chart($div, $chartColumns, $compareTable); $chartData[$metric] = $chart; echo "<div id=\"{$div}\" class=\"chart\"></div>\n"; }