Skip to content

Commit e38b4a4

Browse files
authored
Merge pull request #50 from score-p/issue-49
Implement a decorator to manually instrument functions * decorator can be used to specify user region names * if no region name is specified the region is only added if the instrumenter is disabled * fix a bug in the dummy instrumenter, which did not even lunch the program
2 parents cc0915e + a90132b commit e38b4a4

8 files changed

Lines changed: 232 additions & 131 deletions

File tree

README.md

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,39 @@ with scorep.user.region("region_name"):
5353
do_something()
5454
```
5555

56-
The traditional calls to define a region and log some parameters, still exists:
56+
Since version 2.1 the python bindings support also decorators for functions:
57+
58+
```
59+
@scorep.user.region("region_name")
60+
def do_something():
61+
#do some things
62+
```
63+
If no region name is given, the function name will be used e.g.:
64+
65+
```
66+
@scorep.user.region()
67+
def do_something():
68+
#do some things
69+
```
70+
71+
will result in `__main__:do_something`.
72+
73+
The traditional calls to define a region still exists, but the usage is discouraged:
74+
75+
```
76+
scorep.user.region_begin("region_name")
77+
scorep.user.region_end("region_name")
78+
```
79+
80+
User parameters can be used in any case:
5781

5882
```
59-
scorep.user.region_begin(name)
6083
scorep.user.parameter_int(name, val)
6184
scorep.user.parameter_uint(name, val)
6285
scorep.user.parameter_string(name, string)
63-
scorep.user.region_end(name)
6486
```
6587

66-
`name` defines the name of the parameter or region, while `val` or `string` represents the value that is passed to Score-P.
88+
where `name` defines the name of the parameter or region, while `val` or `string` represents the value that is passed to Score-P.
6789

6890
Disabeling the recording with Score-P is still also possilbe:
6991

@@ -72,7 +94,7 @@ scorep.user.enable_recording()
7294
scorep.user.disable_recording()
7395
```
7496

75-
However, please be aware that the runtime impact is rather small, as the instrumenter is still active. For details about the instrumenter, please see [Instrumenter](#Instrumenter).
97+
However, please be aware that the runtime impact of disabeling Score-P is rather small, as the instrumenter is still active. For details about the instrumenter, please see [Instrumenter](#Instrumenter).
7698

7799
### Instrumenter
78100
With version 2.0 of the python bindings, the term "instrumenter" is introduced. The instrumenter describes the class that maps the Python `trace` or `profile` events to Score-P. Please be aware, that `trace` and `profile` does not refer to the traditional Score-P terms of tracing and profiling, but to the Python functions [sys.settrace](https://docs.python.org/3/library/sys.html#sys.settrace) and [sys.setprofile](https://docs.python.org/3/library/sys.html#sys.setprofile).

scorep/instrumenter.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,13 @@ def __init__(self):
6565
pass
6666

6767
def __enter__(self):
68-
self.tracer_registered = get_instrumenter().register()
68+
self.tracer_registered = scorep.instrumenter.get_instrumenter().get_registered()
69+
if not self.tracer_registered:
70+
scorep.instrumenter.get_instrumenter().register()
6971

7072
def __exit__(self, exc_type, exc_value, traceback):
71-
self.tracer_registered = get_instrumenter().unregister()
73+
if not self.tracer_registered:
74+
scorep.instrumenter.get_instrumenter().unregister()
7275

7376

7477
class disable():
@@ -85,7 +88,10 @@ def __init__(self):
8588
pass
8689

8790
def __enter__(self):
88-
self.tracer_registered = get_instrumenter().unregister()
91+
self.tracer_registered = scorep.instrumenter.get_instrumenter().get_registered()
92+
if self.tracer_registered:
93+
scorep.instrumenter.get_instrumenter().unregister()
8994

9095
def __exit__(self, exc_type, exc_value, traceback):
91-
self.tracer_registered = get_instrumenter().register()
96+
if self.tracer_registered:
97+
scorep.instrumenter.get_instrumenter().register()

scorep/instrumenters/dummy.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,19 @@ def run(self, cmd):
1818
pass
1919

2020
def runctx(self, cmd, globals=None, locals=None):
21-
pass
21+
if globals is None:
22+
globals = {}
23+
if locals is None:
24+
locals = {}
25+
exec(cmd, globals, locals)
2226

2327
def runfunc(self, func, *args, **kw):
2428
pass
2529

26-
def user_region_begin(self, name, file_name=None, line_number=None):
30+
def region_begin(self, module_name, function_name, file_name, line_number):
2731
pass
2832

29-
def user_region_end(self, name):
33+
def region_end(self, module_name, function_name):
3034
pass
3135

3236
def rewind_begin(self, name, file_name=None, line_number=None):

scorep/instrumenters/scorep_profile.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,28 +102,12 @@ def globaltrace_lt(self, frame, why, arg):
102102
else:
103103
return
104104

105-
def user_region_begin(self, name, file_name=None, line_number=None):
106-
"""
107-
Begin of an User region. If file_name or line_number is None, both will
108-
bet determined automatically
109-
@param name name of the user region
110-
@param file_name file name of the user region
111-
@param line_number line number of the user region
112-
"""
113-
if file_name is None or line_number is None:
114-
frame = inspect.currentframe().f_back
115-
file_name = frame.f_globals.get('__file__', None)
116-
line_number = frame.f_lineno
117-
if file_name is not None:
118-
full_file_name = os.path.abspath(file_name)
119-
else:
120-
full_file_name = "None"
121-
105+
def region_begin(self, module_name, function_name, file_name, line_number):
122106
self.scorep_bindings.region_begin(
123-
"user", name, full_file_name, line_number)
107+
module_name, function_name, file_name, line_number)
124108

125-
def user_region_end(self, name):
126-
self.scorep_bindings.region_end("user", name)
109+
def region_end(self, module_name, function_name):
110+
self.scorep_bindings.region_end(module_name, function_name)
127111

128112
def rewind_begin(self, name, file_name=None, line_number=None):
129113
"""

scorep/instrumenters/scorep_trace.py

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,28 +102,12 @@ def localtrace_trace(self, frame, why, arg):
102102
self.scorep_bindings.region_end(modulename, code.co_name)
103103
return self.localtrace
104104

105-
def user_region_begin(self, name, file_name=None, line_number=None):
106-
"""
107-
Begin of an User region. If file_name or line_number is None, both will
108-
bet determined automatically
109-
@param name name of the user region
110-
@param file_name file name of the user region
111-
@param line_number line number of the user region
112-
"""
113-
if file_name is None or line_number is None:
114-
frame = inspect.currentframe().f_back
115-
file_name = frame.f_globals.get('__file__', None)
116-
line_number = frame.f_lineno
117-
if file_name is not None:
118-
full_file_name = os.path.abspath(file_name)
119-
else:
120-
full_file_name = "None"
121-
105+
def region_begin(self, module_name, function_name, file_name, line_number):
122106
self.scorep_bindings.region_begin(
123-
"user", name, full_file_name, line_number)
107+
module_name, function_name, file_name, line_number)
124108

125-
def user_region_end(self, name):
126-
self.scorep_bindings.region_end("user", name)
109+
def region_end(self, module_name, function_name):
110+
self.scorep_bindings.region_end(module_name, function_name)
127111

128112
def rewind_begin(self, name, file_name=None, line_number=None):
129113
"""

0 commit comments

Comments
 (0)