-
Notifications
You must be signed in to change notification settings - Fork 1
/
weasyperf.py
executable file
·127 lines (109 loc) · 4.59 KB
/
weasyperf.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python
import argparse
import functools
import os.path
import pathlib
import subprocess
import venv
import pygal
parser = argparse.ArgumentParser(
prog='weasyperf', description='Test WeasyPrint performance.')
parser.add_argument('-s', '--sample', action='append', help='HTML samples.')
parser.add_argument(
'-v', '--version', action='append', help='WeasyPrint versions.')
args = parser.parse_args()
current = pathlib.Path(__file__).parent
venvs = current / 'venvs'
samples = args.sample or sorted(
(path.name for path in (current / 'samples').iterdir()))
versions = args.version or sorted(
(path.name for path in (current / 'versions').iterdir()), reverse=True)
run = functools.partial(
subprocess.run, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
for sample in samples:
path = current / 'samples' / sample
config = pygal.Config()
config.title = f'Time and memory for "{sample}"'
config.x_title = 'Time (seconds)'
config.y_title = 'Memory (megabytes)'
config.dots_size = 0.5
config.show_x_guides = True
xy_graph = pygal.XY(config)
config = pygal.Config()
config.title = f'Memory for "{sample}"'
config.x_title = 'Memory (megabytes)'
mem_graph = pygal.HorizontalBar(config)
config = pygal.Config()
config.title = f'Time for "{sample}"'
config.x_title = 'Time (seconds)'
time_graph = pygal.HorizontalBar(config)
config = pygal.Config()
config.title = f'PDF size for "{sample}"'
config.x_title = 'Size (kilobytes)'
size_graph = pygal.HorizontalBar(config)
for data_file in path.glob('*.dat'):
data_file.unlink()
for version in versions:
if sample == 'json' and version < '43':
# This sample is broken with older versions
continue
if version.startswith('file://'):
file_folder = version[7:]
version = 'file'
version_path = venvs / version
pip = version_path / 'bin' / 'pip'
python = version_path / 'bin' / 'python'
if not pip.exists():
print(f'* Generating virtual environment for WeasyPrint {version}')
version_path.mkdir(parents=True, exist_ok=True)
venv.create(version_path, with_pip=True)
run((pip, 'install', '--upgrade', 'pip'))
run((pip, 'install', '--upgrade', 'setuptools'))
run((pip, 'install', 'memory_profiler'))
print(f'* Installing WeasyPrint {version}')
if version == 'file':
result = run((pip, 'install', '--force', file_folder))
else:
requirements = current / 'versions' / version
if requirements.exists():
print(' (using fixed requirements)')
result = run(
(pip, 'install', '--force', '-r', requirements))
else:
result = run(
(pip, 'install', '--force', f'weasyprint=={version}'))
if result.returncode != 0:
print(
' !!! Installation failed, '
'reinstalling without dependencies !!!')
result = run(
(pip, 'install', '--force', f'weasyprint=={version}'))
if result.returncode != 0:
print(' !!! Reinstallation failed, aborting !!!')
break
print(f'* Rendering {sample} with WeasyPrint {version}')
result = run((
python, '-m', 'mprof', 'run', '-o', path / f'mprof-{version}.dat',
python, '-m', 'weasyprint',
path / f'{sample}.html', path / f'{sample}-{version}.pdf',
))
if result.returncode != 0:
print(' !!! Rendering failed !!!')
break
lines = [
line.split() for line in
(path / f'mprof-{version}.dat').read_text().split('\n') if line]
timestamp = float(lines[1][2])
xy_graph.add(f'{version}', [
[float(line[2]) - timestamp, float(line[1])]
for line in lines if line[0] == 'MEM'])
mem_graph.add(f'{version}', max(
float(line[1]) for line in lines if line[0] == 'MEM'))
time_graph.add(f'{version}', float(lines[-1][2]) - timestamp)
size_graph.add(
f'{version}',
os.path.getsize(path / f'{sample}-{version}.pdf') / 1000)
(path / 'xy_graph.svg').write_bytes(xy_graph.render())
(path / 'mem_graph.svg').write_bytes(mem_graph.render())
(path / 'time_graph.svg').write_bytes(time_graph.render())
(path / 'size_graph.svg').write_bytes(size_graph.render())