forked from frerich/clcache
-
Notifications
You must be signed in to change notification settings - Fork 0
/
performancetests.py
100 lines (81 loc) · 4.05 KB
/
performancetests.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
#!/usr/bin/env python
#
# This file is part of the clcache project.
#
# The contents of this file are subject to the BSD 3-Clause License, the
# full text of which is available in the accompanying LICENSE file at the
# root directory of this project.
#
# In Python unittests are always members, not functions. Silence lint in this file.
# pylint: disable=no-self-use
#
from multiprocessing import cpu_count
import os
import shutil
import subprocess
import sys
import tempfile
import timeit
import unittest
import clcache
PYTHON_BINARY = sys.executable
CLCACHE_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)), "clcache.py")
ASSETS_DIR = os.path.join("tests", "performancetests")
if "CLCACHE_CMD" in os.environ:
CLCACHE_CMD = os.environ['CLCACHE_CMD'].split()
else:
CLCACHE_CMD = [PYTHON_BINARY, CLCACHE_SCRIPT]
def takeTime(code):
start = timeit.default_timer()
code()
return timeit.default_timer() - start
class TestConcurrency(unittest.TestCase):
NUM_SOURCE_FILES = 30
@classmethod
def setUpClass(cls):
for i in range(1, TestConcurrency.NUM_SOURCE_FILES):
shutil.copyfile(
os.path.join(ASSETS_DIR, 'concurrency', 'file01.cpp'),
os.path.join(ASSETS_DIR, 'concurrency', 'file{:02d}.cpp'.format(i+1))
)
cls.sources = []
for i in range(1, TestConcurrency.NUM_SOURCE_FILES+1):
cls.sources.append(os.path.join(ASSETS_DIR, 'concurrency', 'file{:02d}.cpp'.format(i)))
def testConcurrentHitsScaling(self):
with tempfile.TemporaryDirectory() as tempDir:
customEnv = dict(os.environ, CLCACHE_DIR=tempDir)
cache = clcache.Cache(tempDir)
with cache.statistics as stats:
self.assertEqual(stats.numCacheHits(), 0)
self.assertEqual(stats.numCacheMisses(), 0)
self.assertEqual(stats.numCacheEntries(), 0)
# Populate cache
cmd = CLCACHE_CMD + ['/nologo', '/EHsc', '/c'] + TestConcurrency.sources
coldCacheSequential = takeTime(lambda: subprocess.check_call(cmd, env=customEnv))
with cache.statistics as stats:
self.assertEqual(stats.numCacheHits(), 0)
self.assertEqual(stats.numCacheMisses(), len(TestConcurrency.sources))
self.assertEqual(stats.numCacheEntries(), len(TestConcurrency.sources))
# Compile one-by-one, measuring the time.
cmd = CLCACHE_CMD + ['/nologo', '/EHsc', '/c'] + TestConcurrency.sources
hotCacheSequential = takeTime(lambda: subprocess.check_call(cmd, env=customEnv))
with cache.statistics as stats:
self.assertEqual(stats.numCacheHits(), len(TestConcurrency.sources))
self.assertEqual(stats.numCacheMisses(), len(TestConcurrency.sources))
self.assertEqual(stats.numCacheEntries(), len(TestConcurrency.sources))
# Recompile with many concurrent processes, measuring time
cmd = CLCACHE_CMD + ['/nologo', '/EHsc', '/c', '/MP{}'.format(cpu_count())] + TestConcurrency.sources
hotCacheConcurrent = takeTime(lambda: subprocess.check_call(cmd, env=customEnv))
with cache.statistics as stats:
self.assertEqual(stats.numCacheHits(), len(TestConcurrency.sources) * 2)
self.assertEqual(stats.numCacheMisses(), len(TestConcurrency.sources))
self.assertEqual(stats.numCacheEntries(), len(TestConcurrency.sources))
print("Compiling {} source files sequentially, cold cache: {} seconds"
.format(len(TestConcurrency.sources), coldCacheSequential))
print("Compiling {} source files sequentially, hot cache: {} seconds"
.format(len(TestConcurrency.sources), hotCacheSequential))
print("Compiling {} source files concurrently via /MP{}, hot cache: {} seconds"
.format(len(TestConcurrency.sources), cpu_count(), hotCacheConcurrent))
if __name__ == '__main__':
unittest.TestCase.longMessage = True
unittest.main()