Skip to content

Commit 3137708

Browse files
committed
--shuffle --shuffle-seed
1 parent e485ba9 commit 3137708

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

pyperformance/cli.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import sys
55

66
from pyperf import _hooks
7-
87
from pyperformance import __version__, _utils, is_dev, is_installed
98
from pyperformance.commands import (
109
cmd_compare,
@@ -148,6 +147,17 @@ def parse_args():
148147
default=None,
149148
help="number of skipped values per run used to warmup the benchmark",
150149
)
150+
cmd.add_argument(
151+
"--shuffle",
152+
action="store_true",
153+
help="Run selected benchmarks in random order",
154+
)
155+
cmd.add_argument(
156+
"--shuffle-seed",
157+
type=int,
158+
default=None,
159+
help="Seed used when shuffling benchmarks (implies --shuffle)",
160+
)
151161
filter_opts(cmd)
152162

153163
# show

pyperformance/run.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import hashlib
22
import json
33
import os
4+
import random
45
import sys
56
import time
67
import traceback
@@ -67,13 +68,26 @@ def get_loops_from_file(filename):
6768
return loops
6869

6970

71+
def order_benchmarks(benchmarks, *, shuffle=False, shuffle_seed=None):
72+
seq = list(benchmarks)
73+
if shuffle or shuffle_seed is not None:
74+
rng = random.Random(shuffle_seed)
75+
rng.shuffle(seq)
76+
return seq
77+
return sorted(seq)
78+
79+
7080
def run_benchmarks(should_run, python, options):
7181
if options.same_loops is not None:
7282
loops = get_loops_from_file(options.same_loops)
7383
else:
7484
loops = {}
7585

76-
to_run = sorted(should_run)
86+
to_run = order_benchmarks(
87+
should_run,
88+
shuffle=getattr(options, "shuffle", False),
89+
shuffle_seed=getattr(options, "shuffle_seed", None),
90+
)
7791

7892
info = _pythoninfo.get_info(python)
7993
runid = get_run_id(info)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import unittest
2+
3+
from pyperformance.run import order_benchmarks
4+
5+
6+
class OrderBenchmarksTests(unittest.TestCase):
7+
def setUp(self):
8+
self.benchmarks = ["b", "a", "c"]
9+
10+
def test_default_is_sorted(self):
11+
ordered = order_benchmarks(self.benchmarks)
12+
self.assertEqual(ordered, ["a", "b", "c"])
13+
14+
def test_shuffle_seed_implies_shuffle(self):
15+
ordered = order_benchmarks(self.benchmarks, shuffle_seed=123)
16+
self.assertEqual(ordered, ["c", "a", "b"])
17+
18+
def test_shuffle_flag_without_seed_changes_order(self):
19+
sorted_expected = sorted(self.benchmarks)
20+
21+
shuffled_orders = []
22+
for seed in range(10):
23+
ordered = order_benchmarks(self.benchmarks, shuffle=True, shuffle_seed=seed)
24+
self.assertCountEqual(ordered, self.benchmarks)
25+
shuffled_orders.append(tuple(ordered))
26+
27+
self.assertTrue(
28+
any(order != tuple(sorted_expected) for order in shuffled_orders),
29+
"Shuffle should change order for at least one seed in range(10)",
30+
)
31+
32+
33+
if __name__ == "__main__":
34+
unittest.main()

0 commit comments

Comments
 (0)