OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Inspection of the prefetch predictor database. | 6 """Inspection of the prefetch predictor database. |
7 | 7 |
8 On Android, the database can be extracted using: | 8 On Android, the database can be extracted using: |
9 adb pull \ | 9 adb pull \ |
10 '/data/user/0/$package_name/app_chrome/Default/Network Action Predictor' | 10 '/data/user/0/$package_name/app_chrome/Default/Network Action Predictor' |
11 predictor_db | 11 predictor_db |
12 """ | 12 """ |
13 | 13 |
14 import argparse | 14 import argparse |
15 import operator | |
16 import sqlite3 | 15 import sqlite3 |
17 | 16 |
18 from resource_prefetch_predictor_pb2 import ResourceData | 17 from resource_prefetch_predictor_pb2 import (PrefetchData, ResourceData) |
19 | 18 |
20 | 19 |
21 class Entry(object): | 20 class Entry(object): |
22 """Represents an entry in the predictor database.""" | 21 """Represents an entry in the predictor database.""" |
23 def __init__( | 22 def __init__( |
24 self, main_page_url, resource_url, proto_buffer): | 23 self, primary_key, proto_buffer): |
25 self.main_page_url = main_page_url | 24 self.primary_key = primary_key |
26 self.resource_url = resource_url | 25 self.prefetch_data = PrefetchData() |
27 self.proto = ResourceData() | 26 self.prefetch_data.ParseFromString(proto_buffer) |
28 self.proto.ParseFromString(proto_buffer) | |
29 self.confidence = float(self.proto.number_of_hits / ( | |
30 self.proto.number_of_hits + self.proto.number_of_misses)) | |
31 self.score = self._Score() | |
32 | 27 |
33 def _Score(self): | 28 @classmethod |
29 def _ComputeResourceScore(cls, resource): | |
pasko
2016/10/07 13:55:25
Please mention the type of |resource| in the docst
Benoit L
2016/10/07 14:03:10
Done.
| |
34 """Mirrors ResourcePrefetchPredictorTables::ComputeResourceScore.""" | 30 """Mirrors ResourcePrefetchPredictorTables::ComputeResourceScore.""" |
35 priority_multiplier = 1 | 31 priority_multiplier = 1 |
36 type_multiplier = 1 | 32 type_multiplier = 1 |
37 | 33 |
38 if self.proto.priority == ResourceData.REQUEST_PRIORITY_HIGHEST: | 34 if resource.priority == ResourceData.REQUEST_PRIORITY_HIGHEST: |
39 priority_multiplier = 3 | 35 priority_multiplier = 3 |
40 elif self.proto.priority == ResourceData.REQUEST_PRIORITY_MEDIUM: | 36 elif resource.priority == ResourceData.REQUEST_PRIORITY_MEDIUM: |
41 priority_multiplier = 2 | 37 priority_multiplier = 2 |
42 | 38 |
43 if self.proto.resource_type in (ResourceData.RESOURCE_TYPE_STYLESHEET, | 39 if resource.resource_type in (ResourceData.RESOURCE_TYPE_STYLESHEET, |
44 ResourceData.RESOURCE_TYPE_SCRIPT): | 40 ResourceData.RESOURCE_TYPE_SCRIPT): |
45 type_multiplier = 3 | 41 type_multiplier = 3 |
46 elif self.proto.resource_type == ResourceData.RESOURCE_TYPE_FONT_RESOURCE: | 42 elif resource.resource_type == ResourceData.RESOURCE_TYPE_FONT_RESOURCE: |
47 type_multiplier = 2 | 43 type_multiplier = 2 |
48 | 44 |
49 return (100 * (priority_multiplier * 100 + type_multiplier * 10) | 45 return (100 * (priority_multiplier * 100 + type_multiplier * 10) |
50 - self.proto.average_position) | 46 - resource.average_position) |
51 | 47 |
52 @classmethod | 48 @classmethod |
53 def FromRow(cls, row): | 49 def FromRow(cls, row): |
54 """Builds an entry from a database row.""" | 50 """Builds an entry from a database row.""" |
55 return Entry(*row) | 51 return Entry(*row) |
56 | 52 |
57 def __str__(self): | 53 @classmethod |
58 return 'score: %s\nmain_page_url: %s\nconfidence: %f"\n%s' % ( | 54 def _PrettyPrintResource(cls, resource): |
59 self.score, self.main_page_url, self.confidence, self.proto) | 55 print 'score: %d' % cls._ComputeResourceScore(resource) |
56 print resource | |
pasko
2016/10/07 13:55:25
is the default python pretty-print looking good he
Benoit L
2016/10/07 14:03:10
Actually, protocol buffer are already pretty when
| |
60 | 57 |
61 | 58 def PrettyPrintCandidates(self): |
62 def FilterAndSort(entries, domain): | 59 """Prints the candidates for prefetch.""" |
63 """Filters and sorts the entries to be prefetched for a given domain. | 60 print 'primary_key: %s' % self.prefetch_data.primary_key |
64 | 61 for resource in self.prefetch_data.resources: |
65 Uses the default thresholds defined in resource_prefetch_common.cc. | 62 confidence = resource.number_of_hits / ( |
66 """ | 63 resource.number_of_hits + resource.number_of_misses) |
pasko
2016/10/07 13:55:25
perhaps need to explicitly ask for a floating poin
Benoit L
2016/10/07 14:03:10
/facepalm
Thanks!
Done.
| |
67 result = filter( | 64 if resource.number_of_hits < 2 or confidence < .7: |
68 lambda x: ((domain is None or x.main_page_url == domain) | 65 continue |
69 and x.confidence > .7 | 66 self._PrettyPrintResource(resource) |
70 and x.proto.number_of_hits >= 2), entries) | |
71 return sorted(result, key=operator.attrgetter('score'), reverse=True) | |
72 | 67 |
73 | 68 |
74 def DatabaseStats(filename, domain): | 69 def DatabaseStats(filename, domain): |
75 connection = sqlite3.connect(filename) | 70 connection = sqlite3.connect(filename) |
76 c = connection.cursor() | 71 c = connection.cursor() |
77 query = ('SELECT main_page_url, resource_url, proto ' | 72 query = ('SELECT key, proto FROM resource_prefetch_predictor_host') |
78 'FROM resource_prefetch_predictor_host') | |
79 entries = [Entry.FromRow(row) for row in c.execute(query)] | 73 entries = [Entry.FromRow(row) for row in c.execute(query)] |
80 prefetched = FilterAndSort(entries, domain) | 74 for x in entries: |
81 for x in prefetched: | 75 if domain is None or x.primary_key == domain: |
82 print x | 76 x.PrettyPrintCandidates() |
83 | 77 |
84 | 78 |
85 def main(): | 79 def main(): |
86 parser = argparse.ArgumentParser() | 80 parser = argparse.ArgumentParser() |
87 parser.add_argument('-f', dest='database_filename', required=True, | 81 parser.add_argument('-f', dest='database_filename', required=True, |
88 help='Path to the database') | 82 help='Path to the database') |
89 parser.add_argument('-d', dest='domain', default=None, help='Domain') | 83 parser.add_argument('-d', dest='domain', default=None, help='Domain') |
90 args = parser.parse_args() | 84 args = parser.parse_args() |
91 DatabaseStats(args.database_filename, args.domain) | 85 DatabaseStats(args.database_filename, args.domain) |
92 | 86 |
93 | 87 |
94 if __name__ == '__main__': | 88 if __name__ == '__main__': |
95 main() | 89 main() |
OLD | NEW |