/** * Get the relative offset for the video capture (in milliseconds). * This is the time between the first non-timeline event and the * last paint or rasterize event prior to it. * * @param mixed $testPath * @param mixed $run * @param mixed $cached */ function DevToolsGetVideoOffset($testPath, $run, $cached, &$endTime) { $offset = 0; $endTime = 0; $lastEvent = 0; $cachedText = ''; if ($cached) { $cachedText = '_Cached'; } $devToolsFile = "{$testPath}/{$run}{$cachedText}_devtools.json"; if (gz_is_file($devToolsFile)) { $events = json_decode(gz_file_get_contents($devToolsFile), true); if (is_array($events)) { $lastPaint = 0; $startTime = 0; foreach ($events as &$event) { if (is_array($event) && array_key_exists('method', $event)) { $method_class = substr($event['method'], 0, strpos($event['method'], '.')); // calculate the start time stuff if ($method_class === 'Timeline') { $encoded = json_encode($event); $eventTime = DevToolsEventEndTime($event); if ($eventTime && (!$startTime || $eventTime <= $startTime) && (!$lastPaint || $eventTime > $lastPaint)) { if (strpos($encoded, '"type":"ResourceSendRequest"') !== false) { $startTime = DevToolsEventTime($event); } if (strpos($encoded, '"type":"Rasterize"') !== false || strpos($encoded, '"type":"CompositeLayers"') !== false || strpos($encoded, '"type":"Paint"') !== false) { $lastPaint = $eventTime; } } if ($eventTime > $lastEvent && strpos($encoded, '"type":"Resource') !== false) { $lastEvent = $eventTime; } } } } } } if ($startTime && $lastPaint && $lastPaint < $startTime) { $offset = round($startTime - $lastPaint); } if ($startTime && $lastEvent && $lastEvent > $startTime) { $endTime = ceil($lastEvent - $startTime); } return $offset; }
/** * If we have a timeline, figure out what each thread was doing at each point in time. * Basically CPU utilization from the timeline. * * returns an array of threads with each thread being an array of slices (one for * each time period). Each slice is an array of events and the fraction of that * slice that they consumed (with a total maximum of 1 for any slice). */ function DevToolsGetCPUSlices($testPath, $run, $cached) { $count = 0; $slices = null; $devTools = array(); $startOffset = null; $ver = 1; $cacheFile = "{$testPath}/{$run}.{$cached}.devToolsCPUSlices.{$ver}"; if (gz_is_file($cacheFile)) { $slices = json_decode(gz_file_get_contents($cacheFile), true); } if (!isset($slices)) { GetTimeline($testPath, $run, $cached, $devTools, $startOffset); if (isset($devTools) && is_array($devTools) && count($devTools)) { // Do a first pass to get the start and end times as well as the number of threads $threads = array(0 => true); $startTime = 0; $endTime = 0; foreach ($devTools as &$entry) { if (isset($entry['method']) && $entry['method'] == 'Timeline.eventRecorded' && isset($entry['params']['record'])) { $start = DevToolsEventTime($entry); if ($start && (!$startTime || $start < $startTime)) { $startTime = $start; } $end = DevToolsEventEndTime($entry); if ($end && (!$endTime || $end > $endTime)) { $endTime = $end; } $thread = isset($entry['params']['record']['thread']) ? $entry['params']['record']['thread'] : 0; $threads[$thread] = true; } } // create time slice arrays for each thread $slices = array(); foreach ($threads as $id => $bogus) { $slices[$id] = array(); } // create 1ms time slices for the full time if ($endTime > $startTime) { $startTime = floor($startTime); $endTime = ceil($endTime); for ($i = $startTime; $i <= $endTime; $i++) { $ms = intval($i - $startTime); foreach ($threads as $id => $bogus) { $slices[$id][$ms] = array(); } } // Go through each element and account for the time foreach ($devTools as &$entry) { if (isset($entry['method']) && $entry['method'] == 'Timeline.eventRecorded' && isset($entry['params']['record'])) { $count += DevToolsGetEventTimes($entry['params']['record'], $startTime, $slices); } } } } if ($count) { // remove any threads that didn't have actual slices populated $emptyThreads = array(); foreach ($slices as $thread => &$records) { $is_empty = true; foreach ($records as $ms => &$values) { if (count($values)) { $is_empty = false; break; } } if ($is_empty) { $emptyThreads[] = $thread; } } if (count($emptyThreads)) { foreach ($emptyThreads as $thread) { unset($slices[$thread]); } } gz_file_put_contents($cacheFile, json_encode($slices)); } else { $slices = null; } } return $slices; }