-
Notifications
You must be signed in to change notification settings - Fork 86
/
stress_lowlevel.py
100 lines (89 loc) · 3.01 KB
/
stress_lowlevel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""
Code to stress the low-level API as much as possible to expose
any memory leaks or error handling issues.
"""
import curses
import os
import random
import resource
import sys
import time
import tracemalloc
from contextlib import redirect_stdout
import pytest
def main(stdscr):
if len(sys.argv) > 1:
args = sys.argv[1:]
else:
args = ["-n0", "tests/test_lowlevel.py"]
class StressPlugin:
def __init__(self):
self.max_rss = 0
self.max_rss_iter = 0
self.min_rss = 1e100
self.iteration = 0
self.last_print = time.time()
self.memory_start = None
def pytest_sessionstart(self):
if self.memory_start is None:
tracemalloc.start()
self.memory_start = tracemalloc.take_snapshot()
def pytest_sessionfinish(self):
memory_current = tracemalloc.take_snapshot()
rusage = resource.getrusage(resource.RUSAGE_SELF)
if self.max_rss < rusage.ru_maxrss:
self.max_rss = rusage.ru_maxrss
self.max_rss_iter = self.iteration
if self.min_rss > rusage.ru_maxrss:
self.min_rss = rusage.ru_maxrss
# We don't want to flood stdout, so we rate-limit to 1 per second.
if time.time() - self.last_print > 1:
stdscr.clear()
rows, cols = stdscr.getmaxyx()
stdscr.addstr(
0,
0,
"iter\tRSS\tmin\tmax\tmax@iter"[: cols - 1],
)
stdscr.addstr(
1,
0,
"\t".join(
map(
str,
[
self.iteration,
rusage.ru_maxrss,
self.min_rss,
self.max_rss,
self.max_rss_iter,
],
)
)[: cols - 1],
)
stats = memory_current.compare_to(self.memory_start, "traceback")
for i, stat in enumerate(stats[: rows - 3], 1):
stdscr.addstr(i + 2, 0, str(stat)[: cols - 1])
self.last_print = time.time()
stdscr.refresh()
self.iteration += 1
plugin = StressPlugin()
while True:
# We don't want any random variation in the amount of memory
# used from test-to-test.
random.seed(1)
with open(os.devnull, "w") as devnull:
with redirect_stdout(devnull):
result = pytest.main(args, plugins=[plugin])
if result != 0:
exit("TESTS FAILED")
if __name__ == "__main__":
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
try:
main(stdscr)
finally:
curses.echo()
curses.nocbreak()
curses.endwin()