Skip to content

Commit 84b0ac7

Browse files
authored
Add scorep_instrumenter_base to heavily reduce code duplication (#71)
* Add scorep_instrumenter_base to heavily reduce code duplication * Rename ScorepInstrumenterBase to ScorepInstrumenter * Adapt docstring of run * Use bindings region_begin directly * Introduce scorep.instrumenter.utils module
1 parent 294e50c commit 84b0ac7

5 files changed

Lines changed: 187 additions & 259 deletions

File tree

scorep/instrumenters/base_instrumenter.py

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,9 @@
11
__all__ = ['BaseInstrumenter']
22

33
import abc
4-
import os
54
import sys
65

76

8-
def get_module_name(frame):
9-
modulename = frame.f_globals.get('__name__', None)
10-
if modulename is None:
11-
# this is a NUMPY special situation, see NEP-18, and Score-P Issue
12-
# issues #63
13-
if frame.f_code.co_filename == "<__array_function__ internals>":
14-
modulename = "numpy.__array_function__"
15-
else:
16-
modulename = "unkown"
17-
return modulename
18-
19-
20-
def get_file_name(frame):
21-
file_name = frame.f_code.co_filename
22-
if file_name is not None:
23-
full_file_name = os.path.abspath(file_name)
24-
else:
25-
full_file_name = "None"
26-
return full_file_name
27-
28-
297
if sys.version_info >= (3, 4):
308
class _BaseInstrumenter(abc.ABC):
319
pass
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import abc
2+
import inspect
3+
import os
4+
from scorep.instrumenters import base_instrumenter
5+
6+
7+
class ScorepInstrumenter(base_instrumenter.BaseInstrumenter):
8+
"""Base class for all instrumenters using Score-P"""
9+
10+
def __init__(self, scorep_bindings, enable_instrumenter=True):
11+
"""
12+
@param enable_instrumenter true if the tracing shall be initialised.
13+
Please note, that it is still possible to enable the tracing later using register()
14+
"""
15+
self._scorep_bindings = scorep_bindings
16+
self._tracer_registered = False
17+
self._enabled = enable_instrumenter
18+
19+
@abc.abstractmethod
20+
def _enable_instrumenter(self):
21+
"""Actually enable this instrumenter to collect events"""
22+
23+
@abc.abstractmethod
24+
def _disable_instrumenter(self):
25+
"""Stop this instrumenter from collecting events"""
26+
27+
def register(self):
28+
"""Register this instrumenter (collect events)"""
29+
if not self._tracer_registered:
30+
self._enable_instrumenter()
31+
self._tracer_registered = True
32+
33+
def unregister(self):
34+
"""Unregister this instrumenter (stop collecting events)"""
35+
if self._tracer_registered:
36+
self._disable_instrumenter()
37+
self._tracer_registered = False
38+
39+
def get_registered(self):
40+
"""Return whether this instrumenter is currently collecting events"""
41+
return self._tracer_registered
42+
43+
def run(self, cmd, globals=None, locals=None):
44+
"""Run the compiled command under this instrumenter.
45+
46+
When the instrumenter is enabled it is registered prior to the invocation and unregistered afterwards
47+
"""
48+
if globals is None:
49+
globals = {}
50+
if locals is None:
51+
locals = {}
52+
if self._enabled:
53+
self.register()
54+
try:
55+
exec(cmd, globals, locals)
56+
finally:
57+
self.unregister()
58+
59+
def region_begin(self, module_name, function_name, file_name, line_number):
60+
"""Record a region begin event"""
61+
self._scorep_bindings.region_begin(
62+
module_name, function_name, file_name, line_number)
63+
64+
def region_end(self, module_name, function_name):
65+
"""Record a region end event"""
66+
self._scorep_bindings.region_end(module_name, function_name)
67+
68+
def rewind_begin(self, name, file_name=None, line_number=None):
69+
"""
70+
Begin of an Rewind region. If file_name or line_number is None, both will
71+
be determined automatically
72+
@param name name of the user region
73+
@param file_name file name of the user region
74+
@param line_number line number of the user region
75+
"""
76+
if file_name is None or line_number is None:
77+
frame = inspect.currentframe().f_back
78+
file_name = frame.f_globals.get('__file__', None)
79+
line_number = frame.f_lineno
80+
if file_name is not None:
81+
full_file_name = os.path.abspath(file_name)
82+
else:
83+
full_file_name = "None"
84+
85+
self._scorep_bindings.rewind_begin(name, full_file_name, line_number)
86+
87+
def rewind_end(self, name, value):
88+
"""
89+
End of an Rewind region.
90+
@param name name of the user region
91+
@param value True or False, whenether the region shall be rewinded or not.
92+
"""
93+
self._scorep_bindings.rewind_end(name, value)
94+
95+
def oa_region_begin(self, name, file_name=None, line_number=None):
96+
"""
97+
Begin of an Online Access region. If file_name or line_number is None, both will
98+
be determined automatically
99+
@param name name of the user region
100+
@param file_name file name of the user region
101+
@param line_number line number of the user region
102+
"""
103+
if file_name is None or line_number is None:
104+
frame = inspect.currentframe().f_back
105+
file_name = frame.f_globals.get('__file__', None)
106+
line_number = frame.f_lineno
107+
if file_name is not None:
108+
full_file_name = os.path.abspath(file_name)
109+
else:
110+
full_file_name = "None"
111+
112+
self._scorep_bindings.oa_region_begin(name, full_file_name, line_number)
113+
114+
def oa_region_end(self, name):
115+
"""End an Online Access region."""
116+
self._scorep_bindings.oa_region_end(name)
117+
118+
def user_enable_recording(self):
119+
"""Enable writing of trace events in ScoreP"""
120+
self._scorep_bindings.enable_recording()
121+
122+
def user_disable_recording(self):
123+
"""Disable writing of trace events in ScoreP"""
124+
self._scorep_bindings.disable_recording()
125+
126+
def user_parameter_int(self, name, val):
127+
"""Record a parameter of type integer"""
128+
self._scorep_bindings.parameter_int(name, val)
129+
130+
def user_parameter_uint(self, name, val):
131+
"""Record a parameter of type unsigned integer"""
132+
self._scorep_bindings.parameter_string(name, val)
133+
134+
def user_parameter_string(self, name, string):
135+
"""Record a parameter of type string"""
136+
self._scorep_bindings.parameter_string(name, string)
Lines changed: 12 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
__all__ = ['ScorepProfile']
22

33
import sys
4-
import inspect
5-
import os.path
6-
import scorep.instrumenters.base_instrumenter as base_instrumenter
4+
from scorep.instrumenters.utils import get_module_name, get_file_name
5+
from scorep.instrumenters.scorep_instrumenter import ScorepInstrumenter
76

87
try:
98
import threading
@@ -23,133 +22,28 @@ def _unsetprofile():
2322
threading.setprofile(None)
2423

2524

26-
class ScorepProfile(base_instrumenter.BaseInstrumenter):
27-
def __init__(self, scorep_bindings, enable_instrumenter=True):
28-
"""
29-
@param enable_instrumenter true if the tracing shall be initialised.
30-
Please note, that it is still possible to enable the tracing later using register()
31-
"""
32-
global global_instrumenter
33-
global_instrumenter = self
34-
self.tracer_registered = False
35-
36-
self.scorep_bindings = scorep_bindings
37-
self.globaltrace = self.globaltrace_lt
38-
self.enable_instrumenter = enable_instrumenter
39-
40-
def register(self):
41-
self.tracer_registered = True
42-
_setprofile(self.globaltrace)
25+
class ScorepProfile(ScorepInstrumenter):
26+
def _enable_instrumenter(self):
27+
_setprofile(self._globaltrace)
4328

44-
def unregister(self):
29+
def _disable_instrumenter(self):
4530
_unsetprofile()
46-
self.tracer_registered = False
4731

48-
def get_registered(self):
49-
return self.tracer_registered
50-
51-
def run(self, cmd, globals=None, locals=None):
52-
if globals is None:
53-
globals = {}
54-
if locals is None:
55-
locals = {}
56-
if self.enable_instrumenter:
57-
self.register()
58-
try:
59-
exec(cmd, globals, locals)
60-
finally:
61-
self.unregister()
62-
63-
def globaltrace_lt(self, frame, why, arg):
32+
def _globaltrace(self, frame, why, arg):
6433
"""Handler for call events.
6534
6635
If the code block being entered is to be ignored, returns `None',
6736
else returns self.localtrace.
6837
"""
6938
if why == 'call':
7039
code = frame.f_code
71-
modulename = base_instrumenter.get_module_name(frame)
40+
modulename = get_module_name(frame)
7241
if not code.co_name == "_unsetprofile" and not modulename[:6] == "scorep":
73-
full_file_name = base_instrumenter.get_file_name(frame)
42+
full_file_name = get_file_name(frame)
7443
line_number = code.co_firstlineno
75-
self.scorep_bindings.region_begin(
76-
modulename, code.co_name, full_file_name, line_number)
77-
return
44+
self._scorep_bindings.region_begin(modulename, code.co_name, full_file_name, line_number)
7845
elif why == 'return':
7946
code = frame.f_code
80-
modulename = base_instrumenter.get_module_name(frame)
47+
modulename = get_module_name(frame)
8148
if not code.co_name == "_unsetprofile" and not modulename[:6] == "scorep":
82-
self.scorep_bindings.region_end(modulename, code.co_name)
83-
else:
84-
return
85-
86-
def region_begin(self, module_name, function_name, file_name, line_number):
87-
self.scorep_bindings.region_begin(
88-
module_name, function_name, file_name, line_number)
89-
90-
def region_end(self, module_name, function_name):
91-
self.scorep_bindings.region_end(module_name, function_name)
92-
93-
def rewind_begin(self, name, file_name=None, line_number=None):
94-
"""
95-
Begin of an Rewind region. If file_name or line_number is None, both will
96-
bet determined automatically
97-
@param name name of the user region
98-
@param file_name file name of the user region
99-
@param line_number line number of the user region
100-
"""
101-
if file_name is None or line_number is None:
102-
frame = inspect.currentframe().f_back
103-
file_name = frame.f_globals.get('__file__', None)
104-
line_number = frame.f_lineno
105-
if file_name is not None:
106-
full_file_name = os.path.abspath(file_name)
107-
else:
108-
full_file_name = "None"
109-
110-
self.scorep_bindings.rewind_begin(name, full_file_name, line_number)
111-
112-
def rewind_end(self, name, value):
113-
"""
114-
End of an Rewind region.
115-
@param name name of the user region
116-
@param value True or False, whenether the region shall be rewinded or not.
117-
"""
118-
self.scorep_bindings.rewind_end(name, value)
119-
120-
def oa_region_begin(self, name, file_name=None, line_number=None):
121-
"""
122-
Begin of an Online Access region. If file_name or line_number is None, both will
123-
bet determined automatically
124-
@param name name of the user region
125-
@param file_name file name of the user region
126-
@param line_number line number of the user region
127-
"""
128-
if file_name is None or line_number is None:
129-
frame = inspect.currentframe().f_back
130-
file_name = frame.f_globals.get('__file__', None)
131-
line_number = frame.f_lineno
132-
if file_name is not None:
133-
full_file_name = os.path.abspath(file_name)
134-
else:
135-
full_file_name = "None"
136-
137-
self.scorep_bindings.oa_region_begin(name, full_file_name, line_number)
138-
139-
def oa_region_end(self, name):
140-
self.scorep_bindings.oa_region_end(name)
141-
142-
def user_enable_recording(self):
143-
self.scorep_bindings.enable_recording()
144-
145-
def user_disable_recording(self):
146-
self.scorep_bindings.disable_recording()
147-
148-
def user_parameter_int(self, name, val):
149-
self.scorep_bindings.parameter_int(name, val)
150-
151-
def user_parameter_uint(self, name, val):
152-
self.scorep_bindings.parameter_string(name, val)
153-
154-
def user_parameter_string(self, name, string):
155-
self.scorep_bindings.parameter_string(name, string)
49+
self._scorep_bindings.region_end(modulename, code.co_name)

0 commit comments

Comments
 (0)