2020import os
2121import random
2222import re
23+ import subprocess
2324
2425from .core import BenchmarkSuite
2526from .google import GoogleBenchmarkCommand , GoogleBenchmark
3435
3536
3637def _rev_or_path_dirname (src , rev_or_path ):
38+ """Return a directory-name-safe identifier for a revision or a path.
39+
40+ If ``rev_or_path`` resolves to a git revision, its full SHA is returned.
41+ Otherwise (e.g. it is a filesystem path), a sanitized form with path
42+ separators replaced is returned.
43+ """
3744 if rev_or_path == ArrowSources .WORKSPACE :
3845 return rev_or_path
3946 try :
4047 sha = git .rev_parse (rev_or_path , git_dir = src .path )
4148 if isinstance (sha , bytes ):
4249 sha = sha .decode ("ascii" )
4350 return sha
44- except Exception :
51+ except subprocess . CalledProcessError :
4552 return rev_or_path .replace ("/" , "_" )
4653
4754
@@ -56,8 +63,13 @@ def regex_filter(re_expr):
5663
5764
5865class BenchmarkRunner :
59- def __init__ (self , suite_filter = None , benchmark_filter = None ,
60- repetitions = DEFAULT_REPETITIONS , repetition_min_time = None ):
66+ def __init__ (
67+ self ,
68+ suite_filter = None ,
69+ benchmark_filter = None ,
70+ repetitions = DEFAULT_REPETITIONS ,
71+ repetition_min_time = None ,
72+ ):
6173 self .suite_filter = suite_filter
6274 self .benchmark_filter = benchmark_filter
6375 self .repetitions = repetitions
@@ -70,12 +82,11 @@ def suites(self):
7082
7183 @staticmethod
7284 def from_rev_or_path (src , root , rev_or_path , cmake_conf , ** kwargs ):
73- raise NotImplementedError (
74- "BenchmarkRunner must implement from_rev_or_path" )
85+ raise NotImplementedError ("BenchmarkRunner must implement from_rev_or_path" )
7586
7687
7788class StaticBenchmarkRunner (BenchmarkRunner ):
78- """ Run suites from a (static) set of suites. """
89+ """Run suites from a (static) set of suites."""
7990
8091 def __init__ (self , suites , ** kwargs ):
8192 self ._suites = suites
@@ -110,6 +121,7 @@ def is_json_result(cls, path_or_str):
110121 def from_json (path_or_str , ** kwargs ):
111122 # .codec imported here to break recursive imports
112123 from .codec import BenchmarkRunnerCodec
124+
113125 if os .path .isfile (path_or_str ):
114126 with open (path_or_str ) as f :
115127 loaded = json .load (f )
@@ -122,11 +134,12 @@ def __repr__(self):
122134
123135
124136class CppBenchmarkRunner (BenchmarkRunner ):
125- """ Run suites from a CMakeBuild. """
137+ """Run suites from a CMakeBuild."""
126138
127- def __init__ (self , build , benchmark_extras , run_id = None ,
128- results_dir = None , ** kwargs ):
129- """ Initialize a CppBenchmarkRunner. """
139+ def __init__ (
140+ self , build , benchmark_extras , run_id = None , results_dir = None , ** kwargs
141+ ):
142+ """Initialize a CppBenchmarkRunner."""
130143 super ().__init__ (** kwargs )
131144 self .build = build
132145 self .benchmark_extras = benchmark_extras
@@ -135,9 +148,11 @@ def __init__(self, build, benchmark_extras, run_id=None,
135148
136149 @staticmethod
137150 def default_configuration (** kwargs ):
138- """ Returns the default benchmark configuration. """
151+ """Returns the default benchmark configuration."""
139152 return CppConfiguration (
140- build_type = "release" , with_tests = False , with_benchmarks = True ,
153+ build_type = "release" ,
154+ with_tests = False ,
155+ with_benchmarks = True ,
141156 with_compute = True ,
142157 with_csv = True ,
143158 with_dataset = True ,
@@ -152,30 +167,32 @@ def default_configuration(**kwargs):
152167 with_snappy = True ,
153168 with_zlib = True ,
154169 with_zstd = True ,
155- ** kwargs )
170+ ** kwargs ,
171+ )
156172
157173 @property
158174 def suites_binaries (self ):
159- """ Returns a list of benchmark binaries for this build. """
175+ """Returns a list of benchmark binaries for this build."""
160176 # Ensure build is up-to-date to run benchmarks
161177 self .build ()
162178 # Not the best method, but works for now
163179 glob_expr = os .path .join (self .build .binaries_dir , "*-benchmark" )
164180 return {os .path .basename (b ): b for b in glob .glob (glob_expr )}
165181
166182 def suite (self , name , suite_bin ):
167- """ Returns the resulting benchmarks for a given suite. """
168- suite_cmd = GoogleBenchmarkCommand (suite_bin , self .benchmark_filter ,
169- self .benchmark_extras )
183+ """Returns the resulting benchmarks for a given suite."""
184+ suite_cmd = GoogleBenchmarkCommand (
185+ suite_bin , self .benchmark_filter , self .benchmark_extras
186+ )
170187
171188 # Ensure there will be data
172189 benchmark_names = suite_cmd .list_benchmarks ()
173190 if not benchmark_names :
174191 return None
175192
176193 results = suite_cmd .results (
177- repetitions = self .repetitions ,
178- repetition_min_time = self . repetition_min_time )
194+ repetitions = self .repetitions , repetition_min_time = self . repetition_min_time
195+ )
179196 benchmarks = GoogleBenchmark .from_json (results .get ("benchmarks" ))
180197 return BenchmarkSuite (name , benchmarks )
181198
@@ -188,7 +205,7 @@ def list_benchmarks(self):
188205
189206 @property
190207 def suites (self ):
191- """ Returns all suite for a runner. """
208+ """Returns all suite for a runner."""
192209 suite_matcher = regex_filter (self .suite_filter )
193210
194211 suite_found = False
@@ -214,7 +231,7 @@ def suites(self):
214231
215232 @staticmethod
216233 def from_rev_or_path (src , root , rev_or_path , cmake_conf , ** kwargs ):
217- """ Returns a BenchmarkRunner from a path or a git revision.
234+ """Returns a BenchmarkRunner from a path or a git revision.
218235
219236 First, it checks if `rev_or_path` is a valid path (or string) of a json
220237 object that can deserialize to a BenchmarkRunner. If so, it initialize
@@ -230,7 +247,7 @@ def from_rev_or_path(src, root, rev_or_path, cmake_conf, **kwargs):
230247 """
231248 build = None
232249 if StaticBenchmarkRunner .is_json_result (rev_or_path ):
233- kwargs .pop (' benchmark_extras' , None )
250+ kwargs .pop (" benchmark_extras" , None )
234251 return StaticBenchmarkRunner .from_json (rev_or_path , ** kwargs )
235252 elif CMakeBuild .is_build_dir (rev_or_path ):
236253 build = CMakeBuild .from_path (rev_or_path )
@@ -240,6 +257,8 @@ def from_rev_or_path(src, root, rev_or_path, cmake_conf, **kwargs):
240257 root_rev = os .path .join (root , path_rev )
241258 os .makedirs (root_rev , exist_ok = True )
242259
260+ # Clone dir is reused when there is known revision (git sha)
261+ # in <preserve-dir>/sha/arrow
243262 clone_dir = os .path .join (root_rev , "arrow" )
244263 if os .path .isdir (clone_dir ):
245264 src_rev = ArrowSources (clone_dir )
@@ -253,31 +272,31 @@ def from_rev_or_path(src, root, rev_or_path, cmake_conf, **kwargs):
253272 build = cmake_def .build (build_dir )
254273 results_dir = os .path .join (root_rev , "bench" , "run" , run_id )
255274 os .makedirs (results_dir , exist_ok = True )
256- return CppBenchmarkRunner (build , run_id = run_id ,
257- results_dir = results_dir , ** kwargs )
275+ return CppBenchmarkRunner (
276+ build , run_id = run_id , results_dir = results_dir , ** kwargs
277+ )
258278
259279
260280class JavaBenchmarkRunner (BenchmarkRunner ):
261- """ Run suites for Java. """
281+ """Run suites for Java."""
262282
263283 # default repetitions is 5 for Java microbenchmark harness
264284 def __init__ (self , build , ** kwargs ):
265- """ Initialize a JavaBenchmarkRunner. """
285+ """Initialize a JavaBenchmarkRunner."""
266286 self .build = build
267287 super ().__init__ (** kwargs )
268288
269289 @staticmethod
270290 def default_configuration (** kwargs ):
271- """ Returns the default benchmark configuration. """
291+ """Returns the default benchmark configuration."""
272292 return JavaConfiguration (** kwargs )
273293
274294 def suite (self , name ):
275- """ Returns the resulting benchmarks for a given suite. """
295+ """Returns the resulting benchmarks for a given suite."""
276296 # update .m2 directory, which installs target jars
277297 self .build .build ()
278298
279- suite_cmd = JavaMicrobenchmarkHarnessCommand (
280- self .build , self .benchmark_filter )
299+ suite_cmd = JavaMicrobenchmarkHarnessCommand (self .build , self .benchmark_filter )
281300
282301 # Ensure there will be data
283302 benchmark_names = suite_cmd .list_benchmarks ()
@@ -291,7 +310,7 @@ def suite(self, name):
291310
292311 @property
293312 def list_benchmarks (self ):
294- """ Returns all suite names """
313+ """Returns all suite names"""
295314 # Ensure build is up-to-date to run benchmarks
296315 self .build .build ()
297316
@@ -302,7 +321,7 @@ def list_benchmarks(self):
302321
303322 @property
304323 def suites (self ):
305- """ Returns all suite for a runner. """
324+ """Returns all suite for a runner."""
306325 suite_name = "JavaBenchmark"
307326 suite = self .suite (suite_name )
308327
@@ -315,7 +334,7 @@ def suites(self):
315334
316335 @staticmethod
317336 def from_rev_or_path (src , root , rev_or_path , maven_conf , ** kwargs ):
318- """ Returns a BenchmarkRunner from a path or a git revision.
337+ """Returns a BenchmarkRunner from a path or a git revision.
319338
320339 First, it checks if `rev_or_path` is a valid path (or string) of a json
321340 object that can deserialize to a BenchmarkRunner. If so, it initialize
0 commit comments