Files
oc-server3/htdocs/okapi/views/devel/tilereport.php
T
2013-03-26 16:38:26 +01:00

163 lines
5.5 KiB
PHP

<?php
namespace okapi\views\devel\tilereport;
use Exception;
use okapi\Okapi;
use okapi\Cache;
use okapi\Db;
use okapi\OkapiRequest;
use okapi\OkapiRedirectResponse;
use okapi\OkapiHttpResponse;
use okapi\ParamMissing;
use okapi\InvalidParam;
use okapi\OkapiServiceRunner;
use okapi\OkapiInternalRequest;
use okapi\cronjobs\CronJobController;
class View
{
public static function call()
{
# Flush the stats, so the page is fresh upon every request.
require_once($GLOBALS['rootpath']."okapi/cronjobs.php");
CronJobController::force_run("StatsWriterCronJob");
# When services/caches/map/tile method is called, it writes some extra
# stats in the okapi_stats_hourly table. This page retrieves and
# formats these stats in a readable manner (for debugging).
$response = new OkapiHttpResponse();
$response->content_type = "text/plain; charset=utf-8";
ob_start();
$start = isset($_GET['start']) ? $_GET['start'] : date(
"Y-m-d 00:00:00", time() - 7*86400);
$end = isset($_GET['end']) ? $_GET['end'] : date("Y-m-d 23:59:59");
print "From: $start\n";
print " To: $end\n\n";
$rs = Db::query("
select
service_name,
sum(total_calls),
sum(total_runtime)
from okapi_stats_hourly
where
period_start >= '".mysql_real_escape_string($start)."'
and period_start < '".mysql_real_escape_string($end)."'
and service_name like '%caches/map/tile%'
group by service_name
");
$total_calls = 0;
$total_runtime = 0.0;
$calls = array('A' => 0, 'B' => 0, 'C' => 0, 'D' => 0);
$runtime = array('A' => 0.0, 'B' => 0.0, 'C' => 0.0, 'D' => 0.0);
while (list($name, $c, $r) = mysql_fetch_array($rs))
{
if ($name == 'services/caches/map/tile')
{
$total_calls = $c;
$total_runtime = $r;
}
elseif (strpos($name, 'extra/caches/map/tile/checkpoint') === 0)
{
$calls[$name[32]] = $c;
$runtime[$name[32]] = $r;
}
}
if ($total_calls != $calls['A'])
{
print "Partial results. Only ".$calls['A']." out of $total_calls are covered.\n";
print "All other will count as \"unaccounted for\".\n\n";
$total_calls = $calls['A'];
}
$calls_left = $total_calls;
$runtime_left = $total_runtime;
$perc = function($a, $b) { return ($b > 0) ? sprintf("%.1f", 100 * $a / $b)."%" : "(?)"; };
$avg = function($a, $b) { return ($b > 0) ? sprintf("%.4f", $a / $b)."s" : "(?)"; };
$get_stats = function() use (&$calls_left, &$runtime_left, &$total_calls, &$total_runtime, &$perc)
{
return (
str_pad($perc($calls_left, $total_calls), 6, " ", STR_PAD_LEFT).
str_pad($perc($runtime_left, $total_runtime), 7, " ", STR_PAD_LEFT)
);
};
print "%CALLS %TIME Description\n";
print "====== ====== ======================================================================\n";
print $get_stats()." $total_calls responses served. Total runtime: ".sprintf("%.2f", $total_runtime)."s\n";
print "\n";
print " All of these requests needed a TileTree build/lookup. The average runtime of\n";
print " these lookups was ".$avg($runtime['A'], $total_calls).". ".$perc($runtime['A'], $total_runtime)." of total runtime was spent here.\n";
print "\n";
$runtime_left -= $runtime['A'];
print $get_stats()." All calls passed here after ~".$avg($runtime['A'], $total_calls)."\n";
print "\n";
print " Lookup result was then processed and \"image description\" was created. It was\n";
print " passed on to the TileRenderer to compute the ETag hash string. The average runtime\n";
print " of this part was ".$avg($runtime['B'], $total_calls).". ".$perc($runtime['B'], $total_runtime)." of total runtime was spent here.\n";
print "\n";
$runtime_left -= $runtime['B'];
print $get_stats()." All calls passed here after ~".$avg($runtime['A'] + $runtime['B'], $total_calls)."\n";
$etag_hits = $calls['B'] - $calls['C'];
print "\n";
print " $etag_hits of the requests matched the ETag and were served an HTTP 304 response.\n";
print "\n";
$calls_left = $calls['C'];
print $get_stats()." $calls_left calls passed here after ~".$avg($runtime['A'] + $runtime['B'], $total_calls)."\n";
$imagecache_hits = $calls['C'] - $calls['D'];
print "\n";
print " $imagecache_hits of these calls hit the server image cache.\n";
print " ".$perc($runtime['C'], $total_runtime)." of total runtime was spent to find these.\n";
print "\n";
$calls_left = $calls['D'];
$runtime_left -= $runtime['C'];
print $get_stats()." $calls_left calls passed here after ~".$avg($runtime['A'] + $runtime['B'] + $runtime['C'], $total_calls)."\n";
print "\n";
print " These calls required the tile to be rendered. On average, it took\n";
print " ".$avg($runtime['D'], $calls['D'])." to *render* a tile.\n";
print " ".$perc($runtime['D'], $total_runtime)." of total runtime was spent here.\n";
print "\n";
$runtime_left -= $runtime['D'];
print $perc($runtime_left, $total_runtime)." of runtime was unaccounted for (other processing).\n";
print "Average response time was ".$avg($total_runtime, $total_calls).".\n\n";
print "Current okapi_cache score distribution:\n";
$rs = Db::query("
select floor(log2(score)), count(*), sum(length(value))
from okapi_cache
where score is not null
group by floor(log2(score))
");
while (list($log2, $count, $size) = mysql_fetch_array($rs))
{
print $count." elements ($size bytes) with score between ".pow(2, $log2)." and ".pow(2, $log2 + 1).".\n";
}
$response->body = ob_get_clean();
return $response;
}
}