Source Code AnnotationsΒΆ
Users can annotate their workflow code to get end-to-end performance insights. Currently, three techniques are available for this:
Critical path annotation
Synchronous events annotation
Asynchronous events annotation
For critical path annotation, the user can provide pointcut and scope
information for the annotated region. Currently, valid pointcut values are
before
, after
, around
, before_async
, after_async
, and
around_async
. When no pointcut is specified, the default assumption is
around
. We show an example of this below:
#!/usr/bin/python3
import time
import perfflowaspect
import perfflowaspect.aspect
@perfflowaspect.aspect.critical_path()
def foo(msg):
print("foo")
time.sleep(1)
if msg == "hello":
return 1
return 0
def main():
print("Inside main")
for i in range(4):
foo("hello")
return 0
if __name__ == "__main__":
main()
For synchronous event annotation, the user can provide a pointcut, name, and
category for the annotated region. Valid pointcut values are before
,
after
, and around
. The name represents a way to identify the current
function being annotated, and the category can be a filename. An example of this
is shown below:
#!/usr/bin/python3
import time
import os.path
from perfflowaspect import aspect
def foo():
aspect.sync_event("before", "foo", filename)
time.sleep(2)
print("hello")
aspect.sync_event("after", "foo", filename)
def main():
aspect.sync_event("before", "main", filename)
foo()
aspect.sync_event("after", "main", filename)
if __name__ == "__main__":
filename = os.path.basename(__file__)
main()
For asynchronous event annotation, the user can provide a pointcut, name, category, and scope for the annotated region. An example of this is shown below with the help of futures and thread pools:
#!/usr/bin/python3
import os.path
import time
import logging
import threading
from perfflowaspect import aspect
from concurrent.futures import ThreadPoolExecutor
from time import sleep
pool = ThreadPoolExecutor(3)
def bar(message):
aspect.async_event("before", "bar", filename)
sleep(3)
aspect.async_event("after", "bar", filename)
return message
def foo():
aspect.sync_event("before", "foo", filename)
time.sleep(2)
future = pool.submit(bar, ("hello"))
while not future.done():
sleep(1)
print(future.done())
print(future.result())
aspect.sync_event("after", "foo", filename)
def main():
foo()
if __name__ == "__main__":
filename = os.path.basename(__file__)
main()