Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
43bff057
Kaydet (Commit)
43bff057
authored
Şub 24, 2009
tarafından
Jeffrey Yasskin
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Tools/scripts/analyze_dxp.py, a module with some helper functions to
analyze the output of sys.getdxp().
üst
b7019d8e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
130 additions
and
0 deletions
+130
-0
README
Tools/scripts/README
+1
-0
analyze_dxp.py
Tools/scripts/analyze_dxp.py
+129
-0
No files found.
Tools/scripts/README
Dosyayı görüntüle @
43bff057
...
...
@@ -4,6 +4,7 @@ dutree or lll) are also generally useful UNIX tools.
See also the Demo/scripts directory!
analyze_dxp.py Analyzes the result of sys.getdxp()
byext.py Print lines/words/chars stats of files by extension
byteyears.py Print product of a file's size and age
checkappend.py Search for multi-argument .append() calls
...
...
Tools/scripts/analyze_dxp.py
0 → 100644
Dosyayı görüntüle @
43bff057
"""
Some helper functions to analyze the output of sys.getdxp() (which is
only available if Python was built with -DDYNAMIC_EXECUTION_PROFILE).
These will tell you which opcodes have been executed most frequently
in the current process, and, if Python was also built with -DDXPAIRS,
will tell you which instruction _pairs_ were executed most frequently,
which may help in choosing new instructions.
If Python was built without -DDYNAMIC_EXECUTION_PROFILE, importing
this module will raise a RuntimeError.
If you're running a script you want to profile, a simple way to get
the common pairs is:
$ PYTHONPATH=$PYTHONPATH:<python_srcdir>/Tools/scripts
\
./python -i -O the_script.py --args
...
> from analyze_dxp import *
> s = render_common_pairs()
> open('/tmp/some_file', 'w').write(s)
"""
import
copy
import
opcode
import
operator
import
sys
import
threading
if
not
hasattr
(
sys
,
"getdxp"
):
raise
RuntimeError
(
"Can't import analyze_dxp: Python built without"
" -DDYNAMIC_EXECUTION_PROFILE."
)
_profile_lock
=
threading
.
RLock
()
_cumulative_profile
=
sys
.
getdxp
()
# If Python was built with -DDXPAIRS, sys.getdxp() returns a list of
# lists of ints. Otherwise it returns just a list of ints.
def
has_pairs
(
profile
):
"""Returns True if the Python that produced the argument profile
was built with -DDXPAIRS."""
return
len
(
profile
)
>
0
and
isinstance
(
profile
[
0
],
list
)
def
reset_profile
():
"""Forgets any execution profile that has been gathered so far."""
with
_profile_lock
:
sys
.
getdxp
()
# Resets the internal profile
global
_cumulative_profile
_cumulative_profile
=
sys
.
getdxp
()
# 0s out our copy.
def
merge_profile
():
"""Reads sys.getdxp() and merges it into this module's cached copy.
We need this because sys.getdxp() 0s itself every time it's called."""
with
_profile_lock
:
new_profile
=
sys
.
getdxp
()
if
has_pairs
(
new_profile
):
for
first_inst
in
range
(
len
(
_cumulative_profile
)):
for
second_inst
in
range
(
len
(
_cumulative_profile
[
first_inst
])):
_cumulative_profile
[
first_inst
][
second_inst
]
+=
(
new_profile
[
first_inst
][
second_inst
])
else
:
for
inst
in
range
(
len
(
_cumulative_profile
)):
_cumulative_profile
[
inst
]
+=
new_profile
[
inst
]
def
snapshot_profile
():
"""Returns the cumulative execution profile until this call."""
with
_profile_lock
:
merge_profile
()
return
copy
.
deepcopy
(
_cumulative_profile
)
def
common_instructions
(
profile
):
"""Returns the most common opcodes in order of descending frequency.
The result is a list of tuples of the form
(opcode, opname, # of occurrences)
"""
if
has_pairs
(
profile
)
and
profile
:
inst_list
=
profile
[
-
1
]
else
:
inst_list
=
profile
result
=
[(
op
,
opcode
.
opname
[
op
],
count
)
for
op
,
count
in
enumerate
(
inst_list
)
if
count
>
0
]
result
.
sort
(
key
=
operator
.
itemgetter
(
2
),
reverse
=
True
)
return
result
def
common_pairs
(
profile
):
"""Returns the most common opcode pairs in order of descending frequency.
The result is a list of tuples of the form
((1st opcode, 2nd opcode),
(1st opname, 2nd opname),
# of occurrences of the pair)
"""
if
not
has_pairs
(
profile
):
return
[]
result
=
[((
op1
,
op2
),
(
opcode
.
opname
[
op1
],
opcode
.
opname
[
op2
]),
count
)
# Drop the row of single-op profiles with [:-1]
for
op1
,
op1profile
in
enumerate
(
profile
[:
-
1
])
for
op2
,
count
in
enumerate
(
op1profile
)
if
count
>
0
]
result
.
sort
(
key
=
operator
.
itemgetter
(
2
),
reverse
=
True
)
return
result
def
render_common_pairs
(
profile
=
None
):
"""Renders the most common opcode pairs to a string in order of
descending frequency.
The result is a series of lines of the form:
# of occurrences: ('1st opname', '2nd opname')
"""
if
profile
is
None
:
profile
=
snapshot_profile
()
def
seq
():
for
_
,
ops
,
count
in
common_pairs
(
profile
):
yield
"
%
s:
%
s
\n
"
%
(
count
,
ops
)
return
''
.
join
(
seq
())
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment