blob: 9319fb43a5259288658f78061df6a9e20bcc4471 [file] [log] [blame]
#!/usr/bin/python
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Inspection of the prefetch predictor database.
On Android, the database can be extracted using:
adb pull \
'/data/user/0/$package_name/app_chrome/Default/Network Action Predictor'
predictor_db
"""
import argparse
import operator
import sqlite3
class ResourceType(object):
STYLESHEET = 2
SCRIPT = 3
class Entry(object):
"""Represents an entry in the predictor database."""
HEADER = (
'score,main_page_url,resource_type,number_of_hits,number_of_misses,'
'consecutive_misses,average_position,confidence,resource_url')
def __init__(
self, main_page_url, resource_url, resource_type, number_of_hits,
number_of_misses, consecutive_misses, average_position):
self.main_page_url = main_page_url
self.resource_url = resource_url
self.resource_type = resource_type
self.number_of_hits = int(number_of_hits)
self.number_of_misses = int(number_of_misses)
self.consecutive_misses = int(consecutive_misses)
self.average_position = int(average_position)
self.confidence = float(number_of_hits) / (
number_of_hits + number_of_misses)
self.score = self._Score()
def _Score(self):
"""Mirrors ResourcePrefetchPredictorTables::ResourceRow::UpdateScore."""
multiplier = 1
if self.resource_type in (ResourceType.STYLESHEET, ResourceType.SCRIPT):
multiplier = 2
return multiplier * 100 - self.average_position
@classmethod
def FromRow(cls, row):
"""Builds an entry from a database row."""
return Entry(*row)
def __str__(self):
return '%f,%s,%d,%d,%d,%d,%d,%f\t%s' % (
self.score, self.main_page_url, self.resource_type,
self.number_of_hits, self.number_of_misses, self.consecutive_misses,
self.average_position, self.confidence, self.resource_url)
def FilterAndSort(entries, domain):
"""Filters and sorts the entries to be prefetched for a given domain.
Uses the default thresholds defined in resource_prefetch_common.cc.
"""
result = filter(
lambda x: ((domain is None or x.main_page_url == domain)
and x.confidence > .7
and x.number_of_hits >= 2), entries)
return sorted(result, key=operator.attrgetter('score'), reverse=True)
def DatabaseStats(filename, domain):
connection = sqlite3.connect(filename)
c = connection.cursor()
query = ('SELECT main_page_url, resource_url, resource_type, number_of_hits, '
'number_of_misses, consecutive_misses, average_position '
'FROM resource_prefetch_predictor_host')
entries = [Entry.FromRow(row) for row in c.execute(query)]
prefetched = FilterAndSort(entries, domain)
print Entry.HEADER
for x in prefetched:
print x
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-f', dest='database_filename', required=True,
help='Path to the database')
parser.add_argument('-d', dest='domain', default=None, help='Domain')
args = parser.parse_args()
DatabaseStats(args.database_filename, args.domain)
if __name__ == '__main__':
main()