Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Models for loading in chrome. | 5 """Models for loading in chrome. |
| 6 | 6 |
| 7 (Redirect the following to the general model module once we have one) | 7 (Redirect the following to the general model module once we have one) |
| 8 A model is an object with the following methods. | 8 A model is an object with the following methods. |
| 9 CostMs(): return the cost of the model in milliseconds. | 9 CostMs(): return the cost of the model in milliseconds. |
| 10 Set(): set model-specific parameters. | 10 Set(): set model-specific parameters. |
| (...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 283 for c in children: | 283 for c in children: |
| 284 assert n in c.Predecessors() # Integrity checking | 284 assert n in c.Predecessors() # Integrity checking |
| 285 queue.append(c) | 285 queue.append(c) |
| 286 assert len(visited) == len(self._nodes) | 286 assert len(visited) == len(self._nodes) |
| 287 return '\n'.join(output) | 287 return '\n'.join(output) |
| 288 | 288 |
| 289 ## | 289 ## |
| 290 ## Internal items | 290 ## Internal items |
| 291 ## | 291 ## |
| 292 | 292 |
| 293 _CONTENT_TYPE_TO_COLOR = {'html': 'red', 'css': 'green', 'script': 'blue', | 293 _CONTENT_KIND_TO_COLOR = { |
|
blundell
2016/01/21 14:11:38
Worth documenting what these mean?
mattcary
2016/01/21 16:11:35
Done.
| |
| 294 'json': 'purple', 'gif_image': 'grey', | 294 'application': 'blue', |
| 295 'image': 'orange', 'other': 'white'} | 295 'font': 'grey2', |
| 296 'image': 'orange', # This probably catches gifs? | |
|
Benoit L
2016/01/21 14:14:38
it does.
mattcary
2016/01/21 16:11:35
Then this isn't what we want. Well, let me land th
Benoit L
2016/01/21 16:20:03
About as high as deciding on the bike shed color.
| |
| 297 } | |
| 298 | |
| 299 _CONTENT_TYPE_TO_COLOR = { | |
| 300 'html': 'red', | |
| 301 'css': 'green', | |
| 302 'script': 'blue', | |
| 303 'javascript': 'blue', | |
| 304 'json': 'purple', | |
| 305 'gif': 'grey', | |
| 306 'image': 'orange', | |
| 307 'jpeg': 'orange', | |
| 308 'png': 'orange', | |
| 309 'plain': 'brown3', | |
| 310 'octet-stream': 'brown3', | |
| 311 'other': 'white', | |
| 312 } | |
| 296 | 313 |
| 297 # This resource type may induce a timing dependency. See _SplitChildrenByTime | 314 # This resource type may induce a timing dependency. See _SplitChildrenByTime |
| 298 # for details. | 315 # for details. |
| 299 # TODO(mattcary): are these right? | 316 # TODO(mattcary): are these right? |
| 300 _CAN_BE_TIMING_PARENT = set(['script', 'magic-debug-content']) | 317 _CAN_BE_TIMING_PARENT = set(['script', 'magic-debug-content']) |
| 301 _CAN_MAKE_TIMING_DEPENDENCE = set(['json', 'other', 'magic-debug-content']) | 318 _CAN_MAKE_TIMING_DEPENDENCE = set(['json', 'other', 'magic-debug-content']) |
| 302 | 319 |
| 303 class _NodeInfo(object): | 320 class _NodeInfo(object): |
| 304 """Our internal class that adds cost and other information to nodes. | 321 """Our internal class that adds cost and other information to nodes. |
| 305 | 322 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 | 373 |
| 357 def ContentType(self): | 374 def ContentType(self): |
| 358 return self._request.GetContentType() | 375 return self._request.GetContentType() |
| 359 | 376 |
| 360 def ShortName(self): | 377 def ShortName(self): |
| 361 """Returns either the hostname of the resource, or the filename, | 378 """Returns either the hostname of the resource, or the filename, |
| 362 or the end of the path. Tries to include the domain as much as possible. | 379 or the end of the path. Tries to include the domain as much as possible. |
| 363 """ | 380 """ |
| 364 parsed = urlparse.urlparse(self._request.url) | 381 parsed = urlparse.urlparse(self._request.url) |
| 365 path = parsed.path | 382 path = parsed.path |
| 383 hostname = parsed.hostname if parsed.hostname else '?.?.?' | |
| 366 if path != '' and path != '/': | 384 if path != '' and path != '/': |
| 367 last_path = parsed.path.split('/')[-1] | 385 last_path = parsed.path.split('/')[-1] |
| 368 if len(last_path) < 10: | 386 if len(last_path) < 10: |
| 369 if len(path) < 10: | 387 if len(path) < 10: |
| 370 return parsed.hostname + '/' + path | 388 return hostname + '/' + path |
| 371 else: | 389 else: |
| 372 return parsed.hostname + '/..' + parsed.path[-10:] | 390 return hostname + '/..' + parsed.path[-10:] |
| 373 elif len(last_path) > 10: | 391 elif len(last_path) > 10: |
| 374 return parsed.hostname + '/..' + last_path[:5] | 392 return hostname + '/..' + last_path[:5] |
| 375 else: | 393 else: |
| 376 return parsed.hostname + '/..' + last_path | 394 return hostname + '/..' + last_path |
| 377 else: | 395 else: |
| 378 return parsed.hostname | 396 return hostname |
| 379 | 397 |
| 380 def Url(self): | 398 def Url(self): |
| 381 return self._request.url | 399 return self._request.url |
| 382 | 400 |
| 383 def SetEdgeCost(self, child, cost): | 401 def SetEdgeCost(self, child, cost): |
| 384 assert child.Node() in self._node.Successors() | 402 assert child.Node() in self._node.Successors() |
| 385 self._edge_costs[child] = cost | 403 self._edge_costs[child] = cost |
| 386 | 404 |
| 387 def AddEdgeAnnotation(self, s, annotation): | 405 def AddEdgeAnnotation(self, s, annotation): |
| 388 assert s.Node() in self._node.Successors() | 406 assert s.Node() in self._node.Successors() |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 next_index = len(self._nodes) | 474 next_index = len(self._nodes) |
| 457 assert request not in index_by_request | 475 assert request not in index_by_request |
| 458 index_by_request[request] = next_index | 476 index_by_request[request] = next_index |
| 459 node = dag.Node(next_index) | 477 node = dag.Node(next_index) |
| 460 node_info = self._NodeInfo(node, request) | 478 node_info = self._NodeInfo(node, request) |
| 461 self._nodes.append(node) | 479 self._nodes.append(node) |
| 462 self._node_info.append(node_info) | 480 self._node_info.append(node_info) |
| 463 | 481 |
| 464 dependencies = request_dependencies_lens.RequestDependencyLens( | 482 dependencies = request_dependencies_lens.RequestDependencyLens( |
| 465 trace).GetRequestDependencies() | 483 trace).GetRequestDependencies() |
| 466 for child_rq, parent_rq, reason in dependencies: | 484 for parent_rq, child_rq, reason in dependencies: |
| 467 parent = self._node_info[index_by_request[parent_rq]] | 485 parent = self._node_info[index_by_request[parent_rq]] |
| 468 child = self._node_info[index_by_request[child_rq]] | 486 child = self._node_info[index_by_request[child_rq]] |
| 469 edge_cost = child.StartTime() - parent.EndTime() | 487 edge_cost = child.StartTime() - parent.EndTime() |
| 470 if edge_cost < 0: | 488 if edge_cost < 0: |
| 471 edge_cost = 0 | 489 edge_cost = 0 |
| 472 if child.StartTime() < parent.StartTime(): | 490 if child.StartTime() < parent.StartTime(): |
| 473 logging.error('Inverted dependency: %s->%s', | 491 logging.error('Inverted dependency: %s->%s', |
| 474 parent.ShortName(), child.ShortName()) | 492 parent.ShortName(), child.ShortName()) |
| 475 # Note that child.StartTime() < parent.EndTime() appears to happen a | 493 # Note that child.StartTime() < parent.EndTime() appears to happen a |
| 476 # fair amount in practice. | 494 # fair amount in practice. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 542 break | 560 break |
| 543 if end_mark >= len(children_by_end_time): | 561 if end_mark >= len(children_by_end_time): |
| 544 break # It's not possible to rearrange any more children. | 562 break # It's not possible to rearrange any more children. |
| 545 if go_to_next_child: | 563 if go_to_next_child: |
| 546 continue # We can't rearrange this child, but the next child may be | 564 continue # We can't rearrange this child, but the next child may be |
| 547 # eligible. | 565 # eligible. |
| 548 if children_by_end_time[end_mark].EndTime() <= current.StartTime(): | 566 if children_by_end_time[end_mark].EndTime() <= current.StartTime(): |
| 549 current.ReparentTo(parent, children_by_end_time[end_mark]) | 567 current.ReparentTo(parent, children_by_end_time[end_mark]) |
| 550 children_by_end_time[end_mark].AddEdgeAnnotation(current, 'timing') | 568 children_by_end_time[end_mark].AddEdgeAnnotation(current, 'timing') |
| 551 | 569 |
| 570 def _ContentTypeToColor(self, content_type): | |
| 571 if not content_type: | |
| 572 type_str = 'other' | |
| 573 elif '/' in content_type: | |
| 574 kind, type_str = content_type.split('/') | |
| 575 if kind in self._CONTENT_KIND_TO_COLOR: | |
|
blundell
2016/01/21 14:11:38
hmm, also probably worth documenting the relations
mattcary
2016/01/21 16:11:35
I don't really know how these mime-types work. I t
| |
| 576 return self._CONTENT_KIND_TO_COLOR[kind] | |
| 577 else: | |
| 578 type_str = content_type | |
| 579 return self._CONTENT_TYPE_TO_COLOR[type_str] | |
| 580 | |
| 552 def _GraphvizNode(self, index, highlight): | 581 def _GraphvizNode(self, index, highlight): |
| 553 """Returns a graphviz node description for a given node. | 582 """Returns a graphviz node description for a given node. |
| 554 | 583 |
| 555 Args: | 584 Args: |
| 556 index: index of the node. | 585 index: index of the node. |
| 557 highlight: a list of node items to emphasize. Any resource url which | 586 highlight: a list of node items to emphasize. Any resource url which |
| 558 contains any highlight text will be distinguished in the output. | 587 contains any highlight text will be distinguished in the output. |
| 559 | 588 |
| 560 Returns: | 589 Returns: |
| 561 A string describing the resource in graphviz format. | 590 A string describing the resource in graphviz format. |
| 562 The resource is color-coded according to its content type, and its shape | 591 The resource is color-coded according to its content type, and its shape |
| 563 is oval if its max-age is less than 300s (or if it's not cacheable). | 592 is oval if its max-age is less than 300s (or if it's not cacheable). |
| 564 """ | 593 """ |
| 565 node_info = self._node_info[index] | 594 node_info = self._node_info[index] |
| 566 color = self._CONTENT_TYPE_TO_COLOR[node_info.ContentType()] | 595 color = self._ContentTypeToColor(node_info.ContentType()) |
| 567 max_age = node_info.Request().MaxAge() | 596 max_age = node_info.Request().MaxAge() |
| 568 shape = 'polygon' if max_age > 300 else 'oval' | 597 shape = 'polygon' if max_age > 300 else 'oval' |
| 569 styles = ['filled'] | 598 styles = ['filled'] |
| 570 if highlight: | 599 if highlight: |
| 571 for fragment in highlight: | 600 for fragment in highlight: |
| 572 if fragment in node_info.Url(): | 601 if fragment in node_info.Url(): |
| 573 styles.append('dotted') | 602 styles.append('dotted') |
| 574 break | 603 break |
| 575 return ('%d [label = "%s\\n%.2f->%.2f (%.2f)"; style = "%s"; ' | 604 return ('%d [label = "%s\\n%.2f->%.2f (%.2f)"; style = "%s"; ' |
| 576 'fillcolor = %s; shape = %s];\n' | 605 'fillcolor = %s; shape = %s];\n' |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 666 Dict of image url + short name to NodeInfo. | 695 Dict of image url + short name to NodeInfo. |
| 667 """ | 696 """ |
| 668 image_to_info = {} | 697 image_to_info = {} |
| 669 for n in self._node_info: | 698 for n in self._node_info: |
| 670 if (n.ContentType().startswith('image') and | 699 if (n.ContentType().startswith('image') and |
| 671 not self._IsAdUrl(n.Url())): | 700 not self._IsAdUrl(n.Url())): |
| 672 key = str((n.Url(), n.ShortName(), n.StartTime())) | 701 key = str((n.Url(), n.ShortName(), n.StartTime())) |
| 673 assert key not in image_to_info, n.Url() | 702 assert key not in image_to_info, n.Url() |
| 674 image_to_info[key] = n | 703 image_to_info[key] = n |
| 675 return image_to_info | 704 return image_to_info |
| OLD | NEW |