@@ -185,6 +185,14 @@ static void function_call_starred_1000(benchmark::State& state) {
185185}
186186BENCHMARK (function_call_starred_1000)->Unit (benchmark::kMillisecond );
187187
188+ static const char * fibonacci_source =
189+ " def fib(n):\n "
190+ " if n < 2:\n "
191+ " return n\n "
192+ " return fib(n - 1) + fib(n - 2)\n "
193+ " result = fib(20)\n "
194+ " \n " ;
195+
188196static void fibonacci_recursive_20 (benchmark::State& state) {
189197 using clock = std::chrono::steady_clock;
190198 auto nanoseconds = [](clock::duration duration) {
@@ -193,76 +201,175 @@ static void fibonacci_recursive_20(benchmark::State& state) {
193201 };
194202 auto compile_start = clock::now ();
195203 Args* buffs = New_strBuff ();
196- char * pikaAsm = pika_lines2Asm (
197- buffs, (char *)
198- " def fib(n):\n "
199- " if n < 2:\n "
200- " return n\n "
201- " return fib(n - 1) + fib(n - 2)\n "
202- " result = fib(20)\n "
203- " \n " );
204+ char * pikaAsm = pika_lines2Asm (buffs, (char *)fibonacci_source);
204205 ByteCodeFrame bytecode_frame;
205206 byteCodeFrame_init (&bytecode_frame);
206207 byteCodeFrame_appendFromAsm (&bytecode_frame, pikaAsm);
207208 auto compile_end = clock::now ();
208- uint64_t root_create_ns = 0 ;
209+
210+ pikaMemAllocationCountReset ();
211+ auto root_create_start = clock::now ();
212+ PikaObj* pikaMain = newRootObj ((char *)" pikaMain" , New_PikaMain);
213+ auto root_create_end = clock::now ();
214+ uint64_t root_create_allocations = pikaMemAllocationCount ();
215+ uint32_t warm_heap_baseline_bytes = pikaMemNow ();
216+
209217 uint64_t execute_ns = 0 ;
218+ uint64_t execute_allocations = 0 ;
219+ pikaMemMaxReset ();
220+ pikaMemAllocationCountReset ();
221+ for (auto _ : state) {
222+ uint32_t before_execute_allocations = pikaMemAllocationCount ();
223+ auto execute_start = clock::now ();
224+ pikaVM_runByteCodeFrame (pikaMain, &bytecode_frame);
225+ auto execute_end = clock::now ();
226+ execute_allocations +=
227+ pikaMemAllocationCount () - before_execute_allocations;
228+ if (6765 != obj_getInt (pikaMain, (char *)" result" )) {
229+ state.SkipWithError (" recursive fibonacci result mismatch" );
230+ }
231+ execute_ns += nanoseconds (execute_end - execute_start);
232+ }
233+ uint32_t heap_peak_bytes = pikaMemMax ();
234+ uint32_t before_destroy_allocations = pikaMemAllocationCount ();
235+ auto root_destroy_start = clock::now ();
236+ obj_deinit (pikaMain);
237+ auto root_destroy_end = clock::now ();
238+ uint64_t root_destroy_allocations =
239+ pikaMemAllocationCount () - before_destroy_allocations;
240+ byteCodeFrame_deinit (&bytecode_frame);
241+ args_deinit (buffs);
242+
243+ state.counters [" compile_once_ns" ] =
244+ nanoseconds (compile_end - compile_start);
245+ state.counters [" setup_root_create_ns" ] =
246+ nanoseconds (root_create_end - root_create_start);
247+ state.counters [" warm_execute_ns" ] = benchmark::Counter (
248+ execute_ns, benchmark::Counter::kAvgIterations );
249+ state.counters [" teardown_root_destroy_ns" ] =
250+ nanoseconds (root_destroy_end - root_destroy_start);
251+ state.counters [" setup_root_create_allocations" ] =
252+ root_create_allocations;
253+ state.counters [" execute_allocations" ] = benchmark::Counter (
254+ execute_allocations, benchmark::Counter::kAvgIterations );
255+ state.counters [" teardown_root_destroy_allocations" ] =
256+ root_destroy_allocations;
257+ state.counters [" heap_allocations" ] = benchmark::Counter (
258+ execute_allocations, benchmark::Counter::kAvgIterations );
259+ state.counters [" heap_peak_bytes" ] = heap_peak_bytes;
260+ state.counters [" warm_heap_baseline_bytes" ] =
261+ warm_heap_baseline_bytes;
262+ state.counters [" heap_residual_bytes" ] = pikaMemNow ();
263+ state.counters [" root_destroy_count" ] = 1 ;
264+ }
265+ BENCHMARK (fibonacci_recursive_20)->Unit (benchmark::kMillisecond );
266+
267+ static void fibonacci_recursive_20_cold_start (benchmark::State& state) {
268+ using clock = std::chrono::steady_clock;
269+ auto nanoseconds = [](clock::duration duration) {
270+ return std::chrono::duration_cast<std::chrono::nanoseconds>(duration)
271+ .count ();
272+ };
273+ uint64_t root_create_ns = 0 ;
274+ uint64_t compile_ns = 0 ;
275+ uint64_t first_execute_ns = 0 ;
210276 uint64_t root_destroy_ns = 0 ;
277+ uint64_t cleanup_ns = 0 ;
211278 uint64_t root_create_allocations = 0 ;
279+ uint64_t compile_allocations = 0 ;
212280 uint64_t execute_allocations = 0 ;
213- uint64_t root_destroy_allocations = 0 ;
281+ uint64_t destroy_allocations = 0 ;
282+ uint64_t cleanup_allocations = 0 ;
214283 uint32_t heap_peak_bytes = 0 ;
284+ uint32_t heap_residual_bytes = 0 ;
285+
215286 for (auto _ : state) {
216287 pikaMemMaxReset ();
217288 pikaMemAllocationCountReset ();
289+
218290 auto root_create_start = clock::now ();
219291 PikaObj* pikaMain = newRootObj ((char *)" pikaMain" , New_PikaMain);
220292 auto root_create_end = clock::now ();
221- root_create_allocations += pikaMemAllocationCount ();
222- uint32_t before_execute_allocations = pikaMemAllocationCount ();
293+ uint32_t after_root_allocations = pikaMemAllocationCount ();
294+
295+ auto compile_start = clock::now ();
296+ Args* buffs = New_strBuff ();
297+ char * pikaAsm = pika_lines2Asm (buffs, (char *)fibonacci_source);
298+ ByteCodeFrame bytecode_frame;
299+ byteCodeFrame_init (&bytecode_frame);
300+ byteCodeFrame_appendFromAsm (&bytecode_frame, pikaAsm);
301+ auto compile_end = clock::now ();
302+ uint32_t after_compile_allocations = pikaMemAllocationCount ();
303+
223304 auto execute_start = clock::now ();
224305 pikaVM_runByteCodeFrame (pikaMain, &bytecode_frame);
225306 auto execute_end = clock::now ();
226- execute_allocations +=
227- pikaMemAllocationCount () - before_execute_allocations;
307+ uint32_t after_execute_allocations = pikaMemAllocationCount ();
228308 if (6765 != obj_getInt (pikaMain, (char *)" result" )) {
229- state.SkipWithError (" recursive fibonacci result mismatch" );
309+ state.SkipWithError (" cold fibonacci result mismatch" );
230310 }
231- uint32_t before_destroy_allocations = pikaMemAllocationCount ();
311+
232312 auto root_destroy_start = clock::now ();
233313 obj_deinit (pikaMain);
234314 auto root_destroy_end = clock::now ();
235- root_destroy_allocations +=
236- pikaMemAllocationCount () - before_destroy_allocations;
237- root_create_ns += nanoseconds (root_create_end - root_create_start);
238- execute_ns += nanoseconds (execute_end - execute_start);
239- root_destroy_ns += nanoseconds (root_destroy_end - root_destroy_start);
315+ uint32_t after_destroy_allocations = pikaMemAllocationCount ();
316+
317+ auto cleanup_start = clock::now ();
318+ byteCodeFrame_deinit (&bytecode_frame);
319+ args_deinit (buffs);
320+ auto cleanup_end = clock::now ();
321+ uint32_t after_cleanup_allocations = pikaMemAllocationCount ();
322+
323+ root_create_ns +=
324+ nanoseconds (root_create_end - root_create_start);
325+ compile_ns += nanoseconds (compile_end - compile_start);
326+ first_execute_ns += nanoseconds (execute_end - execute_start);
327+ root_destroy_ns +=
328+ nanoseconds (root_destroy_end - root_destroy_start);
329+ cleanup_ns += nanoseconds (cleanup_end - cleanup_start);
330+ root_create_allocations += after_root_allocations;
331+ compile_allocations +=
332+ after_compile_allocations - after_root_allocations;
333+ execute_allocations +=
334+ after_execute_allocations - after_compile_allocations;
335+ destroy_allocations +=
336+ after_destroy_allocations - after_execute_allocations;
337+ cleanup_allocations +=
338+ after_cleanup_allocations - after_destroy_allocations;
240339 heap_peak_bytes = std::max (heap_peak_bytes, pikaMemMax ());
340+ heap_residual_bytes = std::max (heap_residual_bytes, pikaMemNow ());
241341 }
242- byteCodeFrame_deinit (&bytecode_frame);
243- args_deinit (buffs);
244- state.counters [" compile_once_ns" ] =
245- nanoseconds (compile_end - compile_start);
342+
246343 state.counters [" root_create_ns" ] = benchmark::Counter (
247344 root_create_ns, benchmark::Counter::kAvgIterations );
248- state.counters [" execute_ns" ] = benchmark::Counter (
249- execute_ns, benchmark::Counter::kAvgIterations );
345+ state.counters [" compile_ns" ] = benchmark::Counter (
346+ compile_ns, benchmark::Counter::kAvgIterations );
347+ state.counters [" first_execute_ns" ] = benchmark::Counter (
348+ first_execute_ns, benchmark::Counter::kAvgIterations );
250349 state.counters [" root_destroy_ns" ] = benchmark::Counter (
251350 root_destroy_ns, benchmark::Counter::kAvgIterations );
351+ state.counters [" cleanup_ns" ] = benchmark::Counter (
352+ cleanup_ns, benchmark::Counter::kAvgIterations );
252353 state.counters [" root_create_allocations" ] = benchmark::Counter (
253354 root_create_allocations, benchmark::Counter::kAvgIterations );
355+ state.counters [" compile_allocations" ] = benchmark::Counter (
356+ compile_allocations, benchmark::Counter::kAvgIterations );
254357 state.counters [" execute_allocations" ] = benchmark::Counter (
255358 execute_allocations, benchmark::Counter::kAvgIterations );
256359 state.counters [" root_destroy_allocations" ] = benchmark::Counter (
257- root_destroy_allocations, benchmark::Counter::kAvgIterations );
360+ destroy_allocations, benchmark::Counter::kAvgIterations );
361+ state.counters [" cleanup_allocations" ] = benchmark::Counter (
362+ cleanup_allocations, benchmark::Counter::kAvgIterations );
258363 state.counters [" heap_allocations" ] = benchmark::Counter (
259- root_create_allocations + execute_allocations +
260- root_destroy_allocations,
364+ root_create_allocations + compile_allocations +
365+ execute_allocations + destroy_allocations +
366+ cleanup_allocations,
261367 benchmark::Counter::kAvgIterations );
262368 state.counters [" heap_peak_bytes" ] = heap_peak_bytes;
263- state.counters [" heap_residual_bytes" ] = pikaMemNow () ;
369+ state.counters [" heap_residual_bytes" ] = heap_residual_bytes ;
264370}
265- BENCHMARK (fibonacci_recursive_20)->Unit (benchmark::kMillisecond );
371+ BENCHMARK (fibonacci_recursive_20_cold_start)
372+ ->Unit (benchmark::kMillisecond );
266373
267374static void embedded_control_loop_1000 (benchmark::State& state) {
268375 Args* buffs = New_strBuff ();
0 commit comments