]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Tools/scripts/analyze_dxp.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Tools / scripts / analyze_dxp.py
CommitLineData
4710c53d 1"""\r
2Some helper functions to analyze the output of sys.getdxp() (which is\r
3only available if Python was built with -DDYNAMIC_EXECUTION_PROFILE).\r
4These will tell you which opcodes have been executed most frequently\r
5in the current process, and, if Python was also built with -DDXPAIRS,\r
6will tell you which instruction _pairs_ were executed most frequently,\r
7which may help in choosing new instructions.\r
8\r
9If Python was built without -DDYNAMIC_EXECUTION_PROFILE, importing\r
10this module will raise a RuntimeError.\r
11\r
12If you're running a script you want to profile, a simple way to get\r
13the common pairs is:\r
14\r
15$ PYTHONPATH=$PYTHONPATH:<python_srcdir>/Tools/scripts \\r
16./python -i -O the_script.py --args\r
17...\r
18> from analyze_dxp import *\r
19> s = render_common_pairs()\r
20> open('/tmp/some_file', 'w').write(s)\r
21"""\r
22\r
23import copy\r
24import opcode\r
25import operator\r
26import sys\r
27import threading\r
28\r
29if not hasattr(sys, "getdxp"):\r
30 raise RuntimeError("Can't import analyze_dxp: Python built without"\r
31 " -DDYNAMIC_EXECUTION_PROFILE.")\r
32\r
33\r
34_profile_lock = threading.RLock()\r
35_cumulative_profile = sys.getdxp()\r
36\r
37# If Python was built with -DDXPAIRS, sys.getdxp() returns a list of\r
38# lists of ints. Otherwise it returns just a list of ints.\r
39def has_pairs(profile):\r
40 """Returns True if the Python that produced the argument profile\r
41 was built with -DDXPAIRS."""\r
42\r
43 return len(profile) > 0 and isinstance(profile[0], list)\r
44\r
45\r
46def reset_profile():\r
47 """Forgets any execution profile that has been gathered so far."""\r
48 with _profile_lock:\r
49 sys.getdxp() # Resets the internal profile\r
50 global _cumulative_profile\r
51 _cumulative_profile = sys.getdxp() # 0s out our copy.\r
52\r
53\r
54def merge_profile():\r
55 """Reads sys.getdxp() and merges it into this module's cached copy.\r
56\r
57 We need this because sys.getdxp() 0s itself every time it's called."""\r
58\r
59 with _profile_lock:\r
60 new_profile = sys.getdxp()\r
61 if has_pairs(new_profile):\r
62 for first_inst in range(len(_cumulative_profile)):\r
63 for second_inst in range(len(_cumulative_profile[first_inst])):\r
64 _cumulative_profile[first_inst][second_inst] += (\r
65 new_profile[first_inst][second_inst])\r
66 else:\r
67 for inst in range(len(_cumulative_profile)):\r
68 _cumulative_profile[inst] += new_profile[inst]\r
69\r
70\r
71def snapshot_profile():\r
72 """Returns the cumulative execution profile until this call."""\r
73 with _profile_lock:\r
74 merge_profile()\r
75 return copy.deepcopy(_cumulative_profile)\r
76\r
77\r
78def common_instructions(profile):\r
79 """Returns the most common opcodes in order of descending frequency.\r
80\r
81 The result is a list of tuples of the form\r
82 (opcode, opname, # of occurrences)\r
83\r
84 """\r
85 if has_pairs(profile) and profile:\r
86 inst_list = profile[-1]\r
87 else:\r
88 inst_list = profile\r
89 result = [(op, opcode.opname[op], count)\r
90 for op, count in enumerate(inst_list)\r
91 if count > 0]\r
92 result.sort(key=operator.itemgetter(2), reverse=True)\r
93 return result\r
94\r
95\r
96def common_pairs(profile):\r
97 """Returns the most common opcode pairs in order of descending frequency.\r
98\r
99 The result is a list of tuples of the form\r
100 ((1st opcode, 2nd opcode),\r
101 (1st opname, 2nd opname),\r
102 # of occurrences of the pair)\r
103\r
104 """\r
105 if not has_pairs(profile):\r
106 return []\r
107 result = [((op1, op2), (opcode.opname[op1], opcode.opname[op2]), count)\r
108 # Drop the row of single-op profiles with [:-1]\r
109 for op1, op1profile in enumerate(profile[:-1])\r
110 for op2, count in enumerate(op1profile)\r
111 if count > 0]\r
112 result.sort(key=operator.itemgetter(2), reverse=True)\r
113 return result\r
114\r
115\r
116def render_common_pairs(profile=None):\r
117 """Renders the most common opcode pairs to a string in order of\r
118 descending frequency.\r
119\r
120 The result is a series of lines of the form:\r
121 # of occurrences: ('1st opname', '2nd opname')\r
122\r
123 """\r
124 if profile is None:\r
125 profile = snapshot_profile()\r
126 def seq():\r
127 for _, ops, count in common_pairs(profile):\r
128 yield "%s: %s\n" % (count, ops)\r
129 return ''.join(seq())\r