dbworkload 0.8.2__tar.gz → 0.8.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dbworkload
3
- Version: 0.8.2
3
+ Version: 0.8.4
4
4
  Summary: Workload framework
5
5
  License: GPLv3+
6
6
  Author: Fabio Ghirardello
@@ -15,6 +15,7 @@ from threading import Thread
15
15
 
16
16
  import numpy as np
17
17
  import tabulate
18
+ from psutil import cpu_percent, virtual_memory
18
19
 
19
20
  import dbworkload.utils.common
20
21
  from dbworkload.cli.dep import ConnInfo
@@ -31,11 +32,13 @@ from dbworkload.cli.dep import ConnInfo
31
32
  DEFAULT_SLEEP = 3
32
33
  MAX_RETRIES = 3
33
34
  FREQUENCY = 10
35
+ STATS_BUFFER = 8
34
36
 
35
37
  FIFO = "dbworkload.pipe"
36
38
 
37
39
  logger = logging.getLogger("dbworkload")
38
40
 
41
+ force_exit = False
39
42
 
40
43
  HEADERS: list = [
41
44
  "elapsed",
@@ -95,6 +98,12 @@ def signal_handler(sig, frame):
95
98
  frame (_type_):
96
99
  """
97
100
  logger.info("KeyboardInterrupt signal detected. Stopping processes...")
101
+ global force_exit
102
+ if force_exit:
103
+ logger.warning("Forcibly quitting. You're rude!")
104
+ sys.exit(1)
105
+
106
+ force_exit = True
98
107
 
99
108
  # send the poison pill to each proc.
100
109
  # if dbworkload cannot graceful shutdown due
@@ -104,13 +113,15 @@ def signal_handler(sig, frame):
104
113
  # and raise the queue.Full exception, forcing to quit.
105
114
  for q in queues.values():
106
115
  try:
107
- q.put("proc_end", timeout=0.1)
116
+ q.put("proc_end")
108
117
  except queue.Full:
109
118
  logger.error("Timed out")
110
119
  sys.exit(1)
111
120
 
112
121
  logger.debug("Sent poison pill to all procs")
113
- os.remove(FIFO)
122
+
123
+ if os.path.exists(FIFO):
124
+ os.remove(FIFO)
114
125
 
115
126
 
116
127
  def cycle(iterable, backwards=False):
@@ -181,18 +192,15 @@ def run(
181
192
  log_level: str,
182
193
  ):
183
194
  def gracefully_shutdown(by_keyinterrupt: bool = False):
184
- """
185
- wait for final stat reports to come in,
186
- then print final stats and quit
187
- """
195
+ logger.debug("Gracefully shutting down...")
188
196
 
189
197
  end_time = int(time.time())
190
- _s = stats_received
198
+ # _s = stats_received
191
199
 
192
200
  if not by_keyinterrupt:
193
201
  for q in queues.values():
194
202
  try:
195
- q.put("proc_end", timeout=0.1)
203
+ q.put("proc_end")
196
204
  except queue.Full:
197
205
  logger.error("Timed out")
198
206
  sys.exit(1)
@@ -201,20 +209,23 @@ def run(
201
209
  if x.is_alive():
202
210
  x.join()
203
211
 
204
- while True:
205
- try:
206
- msg = to_main_q.get(block=True, timeout=2.0)
207
- if isinstance(msg, list):
208
- _s += 1
209
- stats.add_tds(msg)
210
- if _s >= active_connections:
211
- break
212
- else:
213
- logger.error("Timed out, quitting")
214
- sys.exit(1)
215
-
216
- except queue.Empty:
217
- break
212
+ # Commenting the below as in theory there shouldn't be any stats that
213
+ # comes in *after* the PROC returns. That is, all threads send stats
214
+ # when all threads are returned, then the supervisor returns.
215
+ # while True:
216
+ # try:
217
+ # msg = to_main_q.get(block=True, timeout=2.0)
218
+ # if isinstance(msg, list):
219
+ # _s += 1
220
+ # stats.add_tds(msg)
221
+ # if _s >= active_connections:
222
+ # break
223
+ # else:
224
+ # logger.error("Timed out, quitting")
225
+ # sys.exit(1)
226
+
227
+ # except queue.Empty:
228
+ # break
218
229
 
219
230
  # now that we have all stat reports, calculate the stats one last time.
220
231
  report = stats.calculate_stats(active_connections, end_time)
@@ -374,10 +385,10 @@ def run(
374
385
  )
375
386
  supervisors[x].start()
376
387
 
377
- # report time happens 2 seconds after the stats are received.
388
+ # report time happens STATS_BUFFER seconds after the stats are received.
378
389
  # we add this buffer to make sure we get all the stats reports
379
390
  # from each thread before we aggregate and display
380
- report_time = start_time + FREQUENCY + 2
391
+ report_time = start_time + FREQUENCY + STATS_BUFFER
381
392
 
382
393
  returned_procs = 0
383
394
  active_connections = 0
@@ -478,6 +489,7 @@ def run(
478
489
  active_connections -= 1
479
490
  elif msg == "proc_returned":
480
491
  returned_procs += 1
492
+ logger.debug(f"Stopped processes: {returned_procs}/{procs} ")
481
493
  elif msg == "task_done":
482
494
  returned_threads += 1
483
495
  except queue.Empty:
@@ -501,11 +513,15 @@ def run(
501
513
  sys.exit(1)
502
514
 
503
515
  if time.time() >= report_time:
504
- # if stats_received != active_connections:
505
- # logger.warning("didn't receive all stats reports yet")
516
+ cpu_util = cpu_percent()
517
+ vmem = virtual_memory().percent
518
+ if stats_received != active_connections or cpu_util > 70 or vmem > 70:
519
+ logger.warning(
520
+ f"{stats_received=}, expected={active_connections}. CPU Util={cpu_util}%, Memory={vmem}%"
521
+ )
506
522
 
507
- # remove the 2 seconds added
508
- endtime = int(time.time()) - 2
523
+ # remove the STATS_BUFFER seconds added
524
+ endtime = int(time.time()) - STATS_BUFFER
509
525
 
510
526
  report = stats.calculate_stats(active_connections, endtime)
511
527
 
@@ -580,7 +596,7 @@ def run(
580
596
  report_time += FREQUENCY
581
597
 
582
598
  # pause briefly to prevent the loop from overheating the CPU
583
- time.sleep(0.1)
599
+ time.sleep(0.001)
584
600
 
585
601
  gracefully_shutdown()
586
602
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "dbworkload"
3
- version = "0.8.2"
3
+ version = "0.8.4"
4
4
  description = "Workload framework"
5
5
  authors = ["Fabio Ghirardello"]
6
6
  license = "GPLv3+"
File without changes
File without changes