12
12
import sys
13
13
import tempfile
14
14
import time
15
+ import json
16
+ from collections import defaultdict
15
17
16
18
17
19
class WaiterError (Exception ):
@@ -32,7 +34,7 @@ def __init__(self, name: str, args: List[str], *, cwd: str = None,
32
34
33
35
def start (self ) -> None :
34
36
self .outfile = tempfile .TemporaryFile ()
35
- self .start_time = time .time ()
37
+ self .start_time = time .perf_counter ()
36
38
self .process = Popen (self .args , cwd = self .cwd , env = self .env ,
37
39
stdout = self .outfile , stderr = STDOUT )
38
40
self .pid = self .process .pid
@@ -107,6 +109,9 @@ class Waiter:
107
109
if not waiter.run():
108
110
print('error')
109
111
"""
112
+
113
+ TIMING_FILENAME = 'runtest_timing.json'
114
+
110
115
def __init__ (self , limit : int = 0 , * , verbosity : int = 0 , xfail : List [str ] = []) -> None :
111
116
self .verbosity = verbosity
112
117
self .queue = [] # type: List[LazySubprocess]
@@ -129,6 +134,16 @@ def __init__(self, limit: int = 0, *, verbosity: int = 0, xfail: List[str] = [])
129
134
self .times1 = {} # type: Dict[str, float]
130
135
self .times2 = {} # type: Dict[str, float]
131
136
137
+ # we likely add only a few tasks, so it's ok to put them in front even if they fast
138
+ # much worse if we put them in the back, and one of them turns out to be slow
139
+ self .times : Dict [str , float ] = defaultdict (lambda : float ('inf' ))
140
+ try :
141
+ with open (self .TIMING_FILENAME ) as fp :
142
+ times = json .load (fp )
143
+ self .times .update (times )
144
+ except Exception :
145
+ print ('cannot find runtest timing file' )
146
+
132
147
def add (self , cmd : LazySubprocess ) -> int :
133
148
rv = len (self .queue )
134
149
self .queue .append (cmd )
@@ -161,12 +176,13 @@ def _record_time(self, name: str, elapsed_time: float) -> None:
161
176
162
177
def _poll_current (self ) -> Tuple [int , int ]:
163
178
while True :
164
- time .sleep (.05 )
179
+ time .sleep (.01 )
165
180
for pid in self .current :
166
181
cmd = self .current [pid ][1 ]
167
182
code = cmd .process .poll ()
168
183
if code is not None :
169
- cmd .end_time = time .time ()
184
+ cmd .end_time = time .perf_counter ()
185
+ self .times [cmd .name ] = cmd .end_time - cmd .start_time
170
186
return pid , code
171
187
172
188
def _wait_next (self ) -> Tuple [List [str ], int , int ]:
@@ -239,6 +255,10 @@ def run(self) -> int:
239
255
if self .verbosity == 0 :
240
256
self ._note = Noter (len (self .queue ))
241
257
print ('SUMMARY %d tasks selected' % len (self .queue ))
258
+
259
+ self .queue = sorted (self .queue , key = lambda c : self .times [c .name ], reverse = True )
260
+ print ([t .name for t in self .queue ][:5 ])
261
+
242
262
sys .stdout .flush ()
243
263
# Failed tasks.
244
264
all_failures = [] # type: List[str]
@@ -272,6 +292,12 @@ def run(self) -> int:
272
292
print ('*** OK ***' )
273
293
sys .stdout .flush ()
274
294
295
+ try :
296
+ with open (self .TIMING_FILENAME , 'w' ) as fp :
297
+ json .dump (self .times , fp )
298
+ except Exception :
299
+ print ('cannot save runtest timing file' )
300
+
275
301
return 0
276
302
277
303
0 commit comments