Skip to content

Commit 6de8e0c

Browse files
committed
Support create_graph
1 parent 6ce0ad3 commit 6de8e0c

7 files changed

+123
-28
lines changed

README.md

+15-2
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,24 @@ generator = ParallelExecutor(prf_GIL_impact,
5454
detail_output=True,
5555
output_file="prf_gil_impact_01.txt")
5656

57+
# Run setup, with test execution 20 seconds and zero delay before start
58+
# (without waiting to other executors)
5759
setup=RunSetup(duration_second=20,start_delay=0)
5860

59-
generator.run_bulk_executor(bulk_list=[[1, 1]],
60-
executor_list=[[16, 1, '1x thread'], [8, 2, '2x threads'],[4, 4,'4x threads']],
61+
# Run performance test with:
62+
# data bulk_list with two data sets
63+
# - first has 10 rows and 5 columns as [10, 5]
64+
# - second has 1000 rows and 50 columns as [1000, 50]
65+
# executor_list with six executor sets
66+
# - first line has three executors with 2, 4 and 8 processes each with 2 threads
67+
# - second line has three executors with 2, 4 and 8 processes each with 4 threads
68+
generator.run_bulk_executor(bulk_list=[[10, 5], [1000, 50]],
69+
executor_list=[[2, 2, '2x thread'], [4, 2, '2x thread'],[8, 2,'2x thread'],
70+
[2, 4, '4x thread'], [4, 4, '4x thread'],[8, 4,'4x thread']],
6171
run_setup=setup)
72+
73+
# We made 12 performance tests (two bulk_list x six executor_list) and write
74+
# outputs to the file 'prf_gil_impact_01.txt'
6275
```
6376

6477
## Outputs in text file

cover.bat

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
rem https://coverage.readthedocs.io/en/7.3.2/
1+
rem Setting based on 'https://coverage.readthedocs.io/en/7.3.2/'
22

33
coverage erase
4-
coverage run -m unittest
4+
coverage run -m unittest discover
55
coverage combine
66
coverage report -m
77
coverage-badge -f -o coverage.svg

publish.bat

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#pip install --upgrade setuptools wheel
2-
#pip install --upgrade twine
1+
rem pip install --upgrade setuptools wheel
2+
rem pip install --upgrade twine
33

44
rmdir /S /Q dist
55
rmdir /S /Q build

qgate_perf/parallel_executor.py

+22-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
from platform import python_version
1919
from packaging import version
2020

21+
from qgate_graph.graph_performance import GraphPerformance
22+
from qgate_graph.graph_executor import GraphExecutor
23+
2124
from contextlib import suppress
2225

2326

@@ -54,9 +57,9 @@ def __init__(self,
5457
self._output_file = output_file
5558
self._init_call = init_call
5659

57-
# technical point, how to close Process
60+
# Technical point, how to close Process
5861
# in python >= 3.7 Close() as soft closing
59-
# in python < 3.7 Terminate() as hard closing
62+
# in python < 3.7 Terminate() as hard closing (the Close method does not exist in python lower versions)
6063
self._process_close=True if version.parse(python_version()) >= version.parse("3.7") else False
6164

6265
def _coreThreadClassPool(self, threads, return_key, return_dict, run_setup: RunSetup):
@@ -244,8 +247,6 @@ def _executeCore(self, run_setup: RunSetup, return_dict, processes=2, threads=2)
244247
for process_key in range(processes):
245248
p = Process(target=self._coreThreadClassPool,
246249
args=(threads, process_key, return_dict, run_setup))
247-
# oldversion p = Process(target=self._coreThreadClassPool,
248-
# p = Process(target=self._coreThreadClassPool,
249250
# p = Process(target=self._coreThreadClass, args=(threads, process_key, return_dict, run_setup))
250251
# p = Process(target=ParallelExecutor._coreThread, args=(self.func, threads, process_key, return_dict, run_setup))
251252
# p = Process(target=ParallelExecutor._coreThreadPool, args=(self.func, threads, process_key, return_dict, run_setup))
@@ -271,7 +272,7 @@ def run_bulk_executor(self,
271272
""" Run cykle of bulks in cycle of sequences for function execution
272273
273274
:param bulk_list: list of bulks for execution in format [[rows, columns], ...]
274-
:param executor_list: list of executors for execution in format [[processes, threads], ...]
275+
:param executor_list: list of executors for execution in format [[processes, threads, 'label'], ...]
275276
:param run_setup: setup of execution
276277
:param sleep_between_bulks: sleep between bulks
277278
:return: return state, True - all executions was without exceptions,
@@ -446,3 +447,19 @@ def test_run(self, run_setup: RunSetup=None, print_output=False):
446447
if ret.exception is not None:
447448
return False
448449
return True
450+
451+
def create_graph(self, output_graph_dir="output", picture_dpi=100):
452+
"""
453+
Generate graph based on output from performance tests
454+
455+
:param output_graph_dir: directory for graph outputs
456+
:param picture_dpi: quality of picture (default is 100 DPI)
457+
"""
458+
459+
# TODO: add datetime to the path
460+
#datetime.datetime.now().isoformat("")
461+
graph = GraphPerformance(picture_dpi)
462+
graph.generate_from_file(self._output_file,os.path.join(output_graph_dir,"graph-perf"))
463+
464+
graph = GraphExecutor(picture_dpi)
465+
graph.generate_from_file(self._output_file,os.path.join(output_graph_dir,"graph-exec"))

requirements.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
numpy<=1.24.3
22
psutil~=5.9
33
packaging>=21.3
4+
qgate_graph>=1.3.6
5+
46

tests/test_graph.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import os
2+
import unittest
3+
import logging
4+
from qgate_perf.parallel_executor import ParallelExecutor
5+
from qgate_perf.parallel_probe import ParallelProbe
6+
from qgate_perf.run_setup import RunSetup
7+
from qgate_perf.executor_helper import ExecutorHelper
8+
from qgate_perf.run_return import RunReturn
9+
import time
10+
from os import path
11+
import shutil
12+
13+
def prf_test(run_return: RunReturn, run_setup: RunSetup):
14+
""" Function for performance testing"""
15+
16+
# init (contain executor synchonization, if needed)
17+
probe = ParallelProbe(run_setup)
18+
19+
if run_setup.is_init:
20+
print(f"!!! INIT CALL !!! {run_setup.bulk_row} x {run_setup.bulk_col} [{run_return.probe}]")
21+
22+
while (True):
23+
24+
# START - performance measure for specific part of code
25+
probe.start()
26+
27+
for r in range(run_setup.bulk_row * run_setup.bulk_col):
28+
time.sleep(0.001)
29+
30+
# STOP - performance measure specific part of code
31+
if probe.stop():
32+
break
33+
34+
if run_setup.param("generate_error"):
35+
raise Exception('Simulated error')
36+
37+
# return outputs
38+
run_return.probe=probe
39+
40+
41+
class TestCaseGraph(unittest.TestCase):
42+
OUTPUT_ADR = "../output/test_graph/"
43+
44+
@classmethod
45+
def setUpClass(cls):
46+
shutil.rmtree(TestCaseGraph.OUTPUT_ADR,True)
47+
48+
@classmethod
49+
def tearDownClass(cls):
50+
pass
51+
52+
def test_graph(self):
53+
generator = ParallelExecutor(prf_test,
54+
label="test",
55+
detail_output=True,
56+
output_file=path.join(self.OUTPUT_ADR, "perf_test.txt"))
57+
58+
setup=RunSetup(duration_second=4, start_delay=2)
59+
self.assertTrue(generator.run_bulk_executor([[10,10], [100,10]],
60+
[[1,2,'Austria perf'], [2,2,'Austria perf'], [4,2,'Austria perf']],
61+
# [1,4,'Germany perf'],[2,4,'Germany perf'],[4,4,'Germany perf']],
62+
setup))
63+
generator.create_graph(self.OUTPUT_ADR)

tests/test_perf.py

+17-17
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ def prf_GIL_impact(run_return: RunReturn, run_setup: RunSetup):
4747

4848
class TestCasePerf(unittest.TestCase):
4949

50-
OUTPUT_PERF_ADR = "../output/test_perf/"
50+
OUTPUT_ADR = "../output/test_perf/"
5151
@classmethod
5252
def setUpClass(cls):
53-
shutil.rmtree(TestCasePerf.OUTPUT_PERF_ADR,True)
53+
shutil.rmtree(TestCasePerf.OUTPUT_ADR, True)
5454

5555
@classmethod
5656
def tearDownClass(cls):
@@ -60,15 +60,15 @@ def test_one_run(self):
6060
generator = ParallelExecutor(prf_GIL_impact,
6161
label="GIL_impact",
6262
detail_output=True,
63-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
63+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
6464

6565
self.assertTrue(generator.one_run())
6666

6767
def test_one_run_param(self):
6868
generator = ParallelExecutor(prf_GIL_impact,
6969
label="GIL_impact",
7070
detail_output=True,
71-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
71+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
7272

7373
setting={"aa":10,
7474
"name": "Adam"}
@@ -79,7 +79,7 @@ def test_init_run(self):
7979
generator = ParallelExecutor(prf_GIL_impact,
8080
label="GIL_impact",
8181
detail_output=True,
82-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
82+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
8383

8484
setting={"aa":10,
8585
"name": "Adam"}
@@ -91,7 +91,7 @@ def test_testrun_exception(self):
9191
generator = ParallelExecutor(prf_GIL_impact,
9292
label="GIL_impact",
9393
detail_output=True,
94-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
94+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
9595

9696
setting={"generate_error": "yes"}
9797

@@ -102,15 +102,15 @@ def test_testrun(self):
102102
generator = ParallelExecutor(prf_GIL_impact,
103103
label="GIL_impact",
104104
detail_output=True,
105-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
105+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
106106

107107
self.assertTrue(generator.test_run(print_output=True))
108108

109109
def test_testrun_setup(self):
110110
generator = ParallelExecutor(prf_GIL_impact,
111111
label="GIL_impact",
112112
detail_output=True,
113-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
113+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
114114

115115
setting = {"aa": 10,
116116
"name": "Adam"}
@@ -122,7 +122,7 @@ def test_run(self):
122122
generator = ParallelExecutor(prf_GIL_impact,
123123
label="GIL_impact",
124124
detail_output=True,
125-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
125+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
126126

127127
setup=RunSetup(duration_second=4, start_delay=2)
128128
self.assertTrue(generator.run(2, 2, setup))
@@ -131,7 +131,7 @@ def test_run_exeption(self):
131131
generator = ParallelExecutor(prf_GIL_impact,
132132
label="GIL_impact",
133133
detail_output=True,
134-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
134+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
135135

136136
setting = {"generate_error": "yes"}
137137

@@ -143,7 +143,7 @@ def test_run_executor(self):
143143
generator = ParallelExecutor(prf_GIL_impact,
144144
label="GIL_impact",
145145
detail_output=True,
146-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
146+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
147147

148148
setup=RunSetup(duration_second=4, start_delay=2)
149149
self.assertTrue(generator.run_executor([[1,1], [2,2]], setup))
@@ -152,7 +152,7 @@ def test_run_executor_exception(self):
152152
generator = ParallelExecutor(prf_GIL_impact,
153153
label="GIL_impact",
154154
detail_output=True,
155-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
155+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
156156

157157
setting = {"generate_error": "yes"}
158158

@@ -163,7 +163,7 @@ def test_run_bulk_executor(self):
163163
generator = ParallelExecutor(prf_GIL_impact,
164164
label="GIL_impact",
165165
detail_output=True,
166-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
166+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
167167

168168
setup=RunSetup(duration_second=1, start_delay=0)
169169
self.assertTrue(generator.run_bulk_executor(bulk_list=[[1,2], [1,10]],
@@ -174,7 +174,7 @@ def test_run_bulk_executor_exception(self):
174174
generator = ParallelExecutor(prf_GIL_impact,
175175
label="GIL_impact",
176176
detail_output=True,
177-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
177+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
178178

179179
setting={"generate_error": "yes"}
180180

@@ -187,7 +187,7 @@ def test_run_bulk_executor_helpers(self):
187187
generator = ParallelExecutor(prf_GIL_impact,
188188
label="GIL_impact",
189189
detail_output=True,
190-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
190+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
191191

192192
setup=RunSetup(duration_second=0, start_delay=0)
193193
self.assertTrue(generator.run_bulk_executor(bulk_list= BundleHelper.ROW_1_COL_10_100,
@@ -198,7 +198,7 @@ def test_run_bulk_executor_grow(self):
198198
generator = ParallelExecutor(prf_GIL_impact,
199199
label="GIL_impact",
200200
detail_output=True,
201-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"))
201+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"))
202202

203203
setup=RunSetup(duration_second=1, start_delay=0)
204204
self.assertTrue(generator.run_bulk_executor(bulk_list=[[1,2]],
@@ -213,7 +213,7 @@ def test_run_bulk_executor_initcall(self):
213213
generator = ParallelExecutor(prf_GIL_impact,
214214
label="GIL_impact",
215215
detail_output=True,
216-
output_file=path.join(self.OUTPUT_PERF_ADR,"perf_gil_impact_test.txt"),
216+
output_file=path.join(self.OUTPUT_ADR, "perf_gil_impact_test.txt"),
217217
init_call=InitCallSetting.all())
218218

219219
setup=RunSetup(duration_second=1, start_delay=0)

0 commit comments

Comments
 (0)