# # Copyright (C) 2016 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # import sys SVG_NODE_HEIGHT = 17 FONT_SIZE = 12 def hash_to_float(string): return hash(string) / float(sys.maxsize) def getLegacyColor(method): r = 175 + int(50 * hash_to_float(reversed(method))) g = 60 + int(180 * hash_to_float(method)) b = 60 + int(55 * hash_to_float(reversed(method))) return (r, g, b) def getDSOColor(method): r = 170 + int(80 * hash_to_float(reversed(method))) g = 180 + int(70 * hash_to_float((method))) b = 170 + int(80 * hash_to_float(reversed(method))) return (r, g, b) def getHeatColor(callsite, total_weight): r = 245 + 10 * (1 - callsite.weight() / total_weight) g = 110 + 105 * (1 - callsite.weight() / total_weight) b = 100 return (r, g, b) def createSVGNode(callsite, depth, f, total_weight, height, color_scheme, nav): x = float(callsite.offset) / total_weight * 100 y = height - (depth + 1) * SVG_NODE_HEIGHT width = callsite.weight() / total_weight * 100 method = callsite.method.replace(">", ">").replace("<", "<") if width <= 0: return if color_scheme == "dso": r, g, b = getDSOColor(callsite.dso) elif color_scheme == "legacy": r, g, b = getLegacyColor(method) else: r, g, b = getHeatColor(callsite, total_weight) r_border, g_border, b_border = [max(0, color - 50) for color in [r, g, b]] f.write( """ %s | %s (%.0f events: %3.2f%%) """ % (callsite.id, ','.join(str(x) for x in nav), method, callsite.dso, callsite.weight(), callsite.weight() / total_weight * 100, x, y, x, y, width, width, r, g, b, r, g, b, r_border, g_border, b_border, x, y + 12, FONT_SIZE)) def renderSVGNodes(flamegraph, depth, f, total_weight, height, color_scheme): for i, child in enumerate(flamegraph.children): # Prebuild navigation target for wasd if i == 0: left_index = 0 else: left_index = flamegraph.children[i - 1].id if i == len(flamegraph.children) - 1: right_index = 0 else: right_index = flamegraph.children[i + 1].id up_index = max(child.children, key=lambda x: x.weight()).id if child.children else 0 # up, left, down, right nav = [up_index, left_index, flamegraph.id, right_index] createSVGNode(child, depth, f, total_weight, height, color_scheme, nav) # Recurse down renderSVGNodes(child, depth + 1, f, total_weight, height, color_scheme) def renderSearchNode(f): f.write( """ Search """) def renderUnzoomNode(f): f.write( """