@@ -25,6 +25,7 @@ def fill_buffer(
2525 """Fill the given buffer up to the given amount of days, one sample per minute."""
2626 random .seed (0 )
2727 basetime = datetime (2022 , 1 , 1 )
28+ print ("..filling" , end = "" , flush = True )
2829
2930 for day in range (days ):
3031 # Push in random order
@@ -35,11 +36,8 @@ def fill_buffer(
3536 )
3637
3738
38- def test_days (days : int , buffer : OrderedRingBuffer [int , Any ]) -> None :
39- """Fills a buffer completely up and then gets the data for each of the 29 days."""
40- print ("." , end = "" , flush = True )
41-
42- fill_buffer (days , buffer , int )
39+ def test_days (days : int , buffer : OrderedRingBuffer [T , Any ]) -> None :
40+ """Gets the data for each of the 29 days."""
4341
4442 basetime = datetime (2022 , 1 , 1 )
4543
@@ -50,119 +48,167 @@ def test_days(days: int, buffer: OrderedRingBuffer[int, Any]) -> None:
5048 )
5149
5250
53- def test_slices (days : int , buffer : OrderedRingBuffer [T , Any ]) -> None :
51+ def test_slices (days : int , buffer : OrderedRingBuffer [T , Any ], median : bool ) -> None :
5452 """Benchmark slicing.
5553
5654 Takes a buffer, fills it up and then excessively gets
5755 the data for each day to calculate the average/median.
5856 """
59- print ("." , end = "" , flush = True )
60- fill_buffer (days , buffer , float )
6157
62- # Chose uneven starting point so that for the first/last window data has to
63- # be copied
64- basetime = datetime (2022 , 1 , 1 , 0 , 5 , 13 , 88 )
58+ basetime = datetime (2022 , 1 , 1 )
6559
66- total_avg = 0.0
67- total_median = 0.0
60+ total = 0.0
6861
69- for _ in range (5 ):
62+ for _ in range (3 ):
7063 for day in range (days ):
7164 minutes = buffer .window (
7265 basetime + timedelta (days = day ), basetime + timedelta (days = day + 1 )
7366 )
7467
75- total_avg += float (np .average (minutes ))
76- total_median += float (np .median (minutes ))
68+ if median :
69+ total += float (np .median (minutes ))
70+ else :
71+ total += float (np .average (minutes ))
7772
7873
79- def test_29_days_list () -> None :
74+ def test_29_days_list (num_runs : int ) -> dict :
8075 """Run the 29 day test on the list backend."""
81- test_days (29 , OrderedRingBuffer ([0 ] * MINUTES_IN_29_DAYS , timedelta (minutes = 1 )))
8276
77+ days = 29
78+ buffer = OrderedRingBuffer ([0 ] * MINUTES_IN_29_DAYS , timedelta (minutes = 1 ))
79+
80+ fill_time = timeit .Timer (lambda : fill_buffer (days , buffer , int )).timeit (number = 1 )
81+ test_time = timeit .Timer (lambda : test_days (days , buffer )).timeit (number = num_runs )
82+ return {"fill" : fill_time , "test" : test_time }
8383
84- def test_29_days_array () -> None :
84+
85+ def test_29_days_array (num_runs : int ) -> dict :
8586 """Run the 29 day test on the array backend."""
86- test_days (
87- 29 ,
88- OrderedRingBuffer (
89- np .empty (
90- shape = MINUTES_IN_29_DAYS ,
91- ),
92- timedelta (minutes = 1 ),
87+ days = 29
88+ buffer = OrderedRingBuffer (
89+ np .empty (
90+ shape = MINUTES_IN_29_DAYS ,
9391 ),
92+ timedelta (minutes = 1 ),
9493 )
9594
95+ fill_time = timeit .Timer (lambda : fill_buffer (days , buffer , int )).timeit (number = 1 )
96+ test_time = timeit .Timer (lambda : test_days (days , buffer )).timeit (number = num_runs )
97+ return {"fill" : fill_time , "test" : test_time }
98+
9699
97- def test_29_days_slicing_list () -> None :
100+ def test_29_days_slicing_list (num_runs : int ) -> dict :
98101 """Run slicing tests on list backend."""
99- test_slices (29 , OrderedRingBuffer ([0 ] * MINUTES_IN_29_DAYS , timedelta (minutes = 1 )))
102+ days = 29
103+ buffer = OrderedRingBuffer ([0 ] * MINUTES_IN_29_DAYS , timedelta (minutes = 1 ))
100104
105+ fill_time = timeit .Timer (lambda : fill_buffer (days , buffer , int )).timeit (number = 1 )
106+ median_test_time = timeit .Timer (
107+ lambda : test_slices (days , buffer , median = True )
108+ ).timeit (number = num_runs )
109+ avg_test_time = timeit .Timer (
110+ lambda : test_slices (days , buffer , median = False )
111+ ).timeit (number = num_runs )
101112
102- def test_29_days_slicing_array () -> None :
113+ return {"fill" : fill_time , "median" : median_test_time , "avg" : avg_test_time }
114+
115+
116+ def test_29_days_slicing_array (num_runs : int ) -> dict :
103117 """Run slicing tests on array backend."""
104- test_slices (
105- 29 ,
106- OrderedRingBuffer (
107- np .empty (
108- shape = MINUTES_IN_29_DAYS ,
109- ),
110- timedelta (minutes = 1 ),
118+ days = 29
119+ buffer = OrderedRingBuffer (
120+ np .empty (
121+ shape = MINUTES_IN_29_DAYS ,
111122 ),
123+ timedelta (minutes = 1 ),
112124 )
113125
126+ fill_time = timeit .Timer (lambda : fill_buffer (days , buffer , int )).timeit (number = 1 )
127+ median_test_time = timeit .Timer (
128+ lambda : test_slices (days , buffer , median = True )
129+ ).timeit (number = num_runs )
130+ avg_test_time = timeit .Timer (
131+ lambda : test_slices (days , buffer , median = False )
132+ ).timeit (number = num_runs )
133+
134+ return {"fill" : fill_time , "median" : median_test_time , "avg" : avg_test_time }
135+
114136
115137def main () -> None :
116138 """Run benchmark.
117139
118140 Result of previous run:
119141
120- Date: Do 22. Dez 15:03:05 CET 2022
142+ Date: Mi 1. Feb 17: 15:02 CET 2023
121143 Result:
122144
123- =========================================
124- Array: ........................................
125- List: ........................................
145+ =====================
146+ Array: ..filling
147+ List: ..filling
126148 Time to fill 29 days with data:
127- Array: 0.09411649959984061 seconds
128- List: 0.0906366748000437 seconds
129- Diff: 0.0034798247997969156
130- =========================================
131- Array: ........................................
132- List: ........................................
133- Filling 29 days and running average & mean on every day:
134- Array: 0.09842290654996759 seconds
135- List: 0.1316629376997298 seconds
136- Diff: -0.03324003114976222
149+ Array: 7.190492740017362 seconds
150+ List: 7.209744154009968 seconds
151+ Diff: -0.019251413992606103
152+ Day-Slices into 29 days with data:
153+ Array: 0.0001254317001439631 seconds
154+ List: 0.00017958255193661898 seconds
155+ Diff: -5.4150851792655874e-05
156+ =====================
157+ Array: ..filling
158+ List: ..filling
159+ Avg of windows of 29 days and running average & mean on every day:
160+ Array: 0.0007975498505402356 seconds
161+ List: 0.0042349924508016555 seconds
162+ Diff: -0.0034374426002614198
163+ Median of windows of 29 days and running average & mean on every day:
164+ Array: 0.0021774103515781462 seconds
165+ List: 0.004992740901070647 seconds
166+ Diff: -0.0028153305494925005
137167 """
138- num_runs = 40
168+ num_runs = 20
139169
140170 print (f" { '' .join (['=' ] * (num_runs + 1 ))} " )
141171 print ("Array: " , end = "" )
142- duration_array = timeit .Timer (test_29_days_array ).timeit (number = num_runs )
172+ array_times = test_29_days_array (num_runs )
173+
143174 print ("\n List: " , end = "" )
144- duration_list = timeit .Timer (test_29_days_list ).timeit (number = num_runs )
175+
176+ list_times = test_29_days_list (num_runs )
145177 print ("" )
146178
147179 print (
148180 "Time to fill 29 days with data:\n \t "
149- + f"Array: { duration_array / num_runs } seconds\n \t "
150- + f"List: { duration_list / num_runs } seconds\n \t "
151- + f"Diff: { duration_array / num_runs - duration_list / num_runs } "
181+ + f"Array: { array_times ['fill' ]} seconds\n \t "
182+ + f"List: { list_times ['fill' ]} seconds\n \t "
183+ + f"Diff: { array_times ['fill' ] - list_times ['fill' ]} "
184+ )
185+
186+ print (
187+ "Day-Slices into 29 days with data:\n \t "
188+ + f"Array: { array_times ['test' ]/ num_runs } seconds\n \t "
189+ + f"List: { list_times ['test' ]/ num_runs } seconds\n \t "
190+ + f"Diff: { array_times ['test' ]/ num_runs - list_times ['test' ]/ num_runs } "
152191 )
153192
154193 print (f" { '' .join (['=' ] * (num_runs + 1 ))} " )
155194 print ("Array: " , end = "" )
156- duration_array = timeit . Timer ( test_29_days_slicing_array ). timeit ( number = num_runs )
195+ slicing_array_times = test_29_days_slicing_array ( num_runs )
157196 print ("\n List: " , end = "" )
158- duration_list = timeit . Timer ( test_29_days_slicing_list ). timeit ( number = num_runs )
197+ slicing_list_times = test_29_days_slicing_list ( num_runs )
159198 print ("" )
160199
161200 print (
162- "Filling 29 days and running average & mean on every day:\n \t "
163- + f"Array: { duration_array / num_runs } seconds\n \t "
164- + f"List: { duration_list / num_runs } seconds\n \t "
165- + f"Diff: { duration_array / num_runs - duration_list / num_runs } "
201+ "Avg of windows of 29 days and running average & mean on every day:\n \t "
202+ + f"Array: { slicing_array_times ['avg' ]/ num_runs } seconds\n \t "
203+ + f"List: { slicing_list_times ['avg' ]/ num_runs } seconds\n \t "
204+ + f"Diff: { slicing_array_times ['avg' ]/ num_runs - slicing_list_times ['avg' ]/ num_runs } "
205+ )
206+
207+ print (
208+ "Median of windows of 29 days and running average & mean on every day:\n \t "
209+ + f"Array: { slicing_array_times ['median' ]/ num_runs } seconds\n \t "
210+ + f"List: { slicing_list_times ['median' ]/ num_runs } seconds\n \t "
211+ + f"Diff: { slicing_array_times ['median' ]/ num_runs - slicing_list_times ['median' ]/ num_runs } "
166212 )
167213
168214
0 commit comments