%% %% This is file `l3benchmark.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% l3benchmark.dtx (with options: `package') %% %% Copyright (C) 2018-2024 The LaTeX Project %% %% It may be distributed and/or modified under the conditions of %% the LaTeX Project Public License (LPPL), either version 1.3c of %% this license or (at your option) any later version. The latest %% version of this license is in the file: %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the "l3experimental bundle" (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% File: l3benchmark.dtx \RequirePackage{expl3} \ProvidesExplPackage{l3benchmark}{2024-03-14}{} {L3 Experimental benchmarking} \fp_new:N \g_benchmark_duration_target_fp \fp_gset:Nn \g_benchmark_duration_target_fp { 1 } \sys_if_timer_exist:F { \fp_gset:Nn \g_benchmark_duration_target_fp { nan } \cs_new_protected:Npn \benchmark_once:n #1 { \msg_error:nn { benchmark } { no-time } } \cs_new_eq:NN \benchmark:n \benchmark_once:n \cs_new_eq:NN \benchmark_once_silent:n \benchmark_once:n \cs_new_eq:NN \benchmark_silent:n \benchmark_once:n \cs_new_protected:Npn \benchmark_tic: { \msg_error:nn { benchmark } { no-time } } \cs_new_eq:NN \benchmark_toc: \benchmark_tic: \msg_new:nnnn { benchmark } { no-time } { The~l3benchmark~package~failed~to~access~a~clock. } { The~current~engine~provides~no~way~to~access~the~system~time. } \msg_critical:nn { benchmark } { no-time } } \int_new:N \g__benchmark_nesting_int \cs_new_protected:Npn \__benchmark_raw:nN #1 { \int_gincr:N \g__benchmark_nesting_int \exp_args:Nc \__benchmark_raw_aux:N { g__benchmark_ \int_use:N \g__benchmark_nesting_int _int } \__benchmark_raw_aux: #1 \__benchmark_raw_end:N } \cs_new_protected:Npn \__benchmark_raw_aux:N #1 { \int_gzero_new:N #1 \cs_gset_protected:Npn \__benchmark_raw_aux: { \int_gset:Nn #1 { \sys_timer: } } } \cs_new_protected:Npn \__benchmark_raw_end:N #1 { \int_gset:Nn #1 { \sys_timer: - \int_use:c { g__benchmark_ \int_use:N \g__benchmark_nesting_int _int } } \int_gdecr:N \g__benchmark_nesting_int } \cs_new_eq:NN \__benchmark_tmp:w ? \cs_new_protected:Npn \__benchmark_raw_replicate:nnN #1 { \int_compare:nNnTF {#1} > { 500000 } { \__benchmark_raw_replicate_large:nnN {#1} } { \__benchmark_raw_replicate_small:nnN {#1} } } \cs_new_protected:Npn \__benchmark_raw_replicate_large:nnN #1#2 { \cs_set:Npe \__benchmark_tmp:w ##1 { \prg_replicate:nn { 5000 } {##1} } \exp_args:Nno \__benchmark_raw_replicate:nnN { #1 / 5000 } { \__benchmark_tmp:w {#2} } } \cs_new_protected:Npn \__benchmark_raw_replicate_small:nnN #1#2 { \cs_set:Npe \__benchmark_tmp:w ##1##2 { \prg_replicate:nn {#1} {##1} } \__benchmark_raw:nN { \__benchmark_tmp:w {#2} { } } \g__benchmark_time_int \exp_args:No \__benchmark_raw_replicate_aux:nnN { \int_use:N \g__benchmark_time_int } {#2} } \cs_new_protected:Npn \__benchmark_raw_replicate_aux:nnN #1#2#3 { \__benchmark_raw:nN { \__benchmark_tmp:w { } {#2} } \g__benchmark_time_int \int_gset:Nn #3 { #1 - \g__benchmark_time_int } \cs_set_eq:NN \__benchmark_tmp:w \prg_do_nothing: } \fp_new:N \g_benchmark_time_fp \fp_new:N \g_benchmark_ops_fp \int_new:N \g__benchmark_duration_int \int_new:N \g__benchmark_time_int \int_new:N \g__benchmark_time_a_int \int_new:N \g__benchmark_time_b_int \int_new:N \g__benchmark_time_c_int \int_new:N \g__benchmark_time_d_int \int_new:N \g__benchmark_repeat_int \tl_new:N \g__benchmark_code_tl \cs_new_protected:Npn \benchmark_once:n #1 { \benchmark_once_silent:n {#1} \__benchmark_display: } \cs_new_protected:Npn \benchmark_once_silent:n #1 { \__benchmark_measure_op: \__benchmark_raw:nN {#1} \g__benchmark_time_int \fp_gset:Nn \g_benchmark_time_fp { \g__benchmark_time_int / 65536 } \fp_gset:Nn \g_benchmark_ops_fp { \g_benchmark_time_fp / \g__benchmark_one_op_fp } } \cs_new_protected:Npn \benchmark:n #1 { \benchmark_silent:n {#1} \__benchmark_display: } \cs_new_protected:Npn \benchmark_silent:n #1 { \__benchmark_measure_op: \tl_gset:Nn \g__benchmark_code_tl {#1} \__benchmark_aux: \fp_gset:Nn \g_benchmark_ops_fp { \g_benchmark_time_fp / \g__benchmark_one_op_fp } } \cs_new_protected:Npn \__benchmark_aux: { \int_gset:Nn \g__benchmark_repeat_int { 1 } \__benchmark_raw:nN { \g__benchmark_code_tl } \g__benchmark_time_int \int_compare:nNnF \g__benchmark_time_int < { \g__benchmark_duration_int / 2 } { \prg_break: } \bool_until_do:nn { \int_compare_p:nNn \g__benchmark_time_int > { \g__benchmark_duration_int / 32 } || \int_compare_p:nNn \g__benchmark_repeat_int > { \c_max_int / 4 } } { \int_gset:Nn \g__benchmark_repeat_int { 4 * \g__benchmark_repeat_int } \__benchmark_run:N \g__benchmark_time_int } \int_gset:Nn \g__benchmark_repeat_int { \fp_to_int:n { max ( 1 , min ( \c_max_int , \g__benchmark_duration_int * \g__benchmark_repeat_int / \int_eval:n { 4 * \g__benchmark_time_int } ) ) } } \int_compare:nNnTF \g__benchmark_repeat_int = 1 { \int_gset_eq:NN \g__benchmark_time_a_int \g__benchmark_time_int } { \__benchmark_run:N \g__benchmark_time_a_int } \__benchmark_run:N \g__benchmark_time_b_int \__benchmark_run:N \g__benchmark_time_c_int \__benchmark_run:N \g__benchmark_time_d_int \int_gset:Nn \g__benchmark_time_int { \int_min:nn { \int_min:nn \g__benchmark_time_a_int \g__benchmark_time_b_int } { \int_min:nn \g__benchmark_time_c_int \g__benchmark_time_d_int } } \prg_break_point: \int_compare:nNnT \g__benchmark_time_int < 3 { \int_gzero:N \g__benchmark_time_int } \fp_gset:Nn \g_benchmark_time_fp { \g__benchmark_time_int / \g__benchmark_repeat_int / 65536 } } \cs_new_protected:Npn \__benchmark_run:N { \exp_args:NNo \__benchmark_raw_replicate:nnN \g__benchmark_repeat_int { \g__benchmark_code_tl } } \fp_new:N \g__benchmark_one_op_fp \cs_new_protected:Npn \__benchmark_measure_op: { \int_gset:Nn \g__benchmark_duration_int { \fp_to_int:n { 65536 * \g_benchmark_duration_target_fp } / 4 } \tl_gset:Nn \g__benchmark_code_tl { \int_gadd:Nn \g__benchmark_duration_int { 0 } } \__benchmark_aux: \fp_gset:Nn \g__benchmark_one_op_fp { max(\g_benchmark_time_fp, 1e-8) } \int_gset:Nn \g__benchmark_duration_int { \fp_to_int:n { 65536 * \g_benchmark_duration_target_fp } } } \cs_new:Npn \__benchmark_fp_to_tl:N #1 { \fp_compare:nTF { abs(#1) < 1000 } { \fp_to_tl:n { round(#1, 2 - logb(#1)) } } { \exp_args:Nf \__benchmark_fp_to_tl_aux:nN { \fp_to_int:n { logb(#1) } } #1 } } \cs_new:Npn \__benchmark_fp_to_tl_aux:nN #1#2 { \fp_to_tl:n { round(#2 * 1e-#1, 2) } e#1 } \cs_new_protected:Npn \__benchmark_display: { \iow_term:e { \__benchmark_fp_to_tl:N \g_benchmark_time_fp \c_space_tl seconds \c_space_tl ( \__benchmark_fp_to_tl:N \g_benchmark_ops_fp \c_space_tl ops) } } \int_new:N \g__benchmark_tictoc_int \seq_new:N \g__benchmark_tictoc_seq \tl_new:N \l__benchmark_tictoc_pop_tl \cs_new:Npn \__benchmark_tictoc_prefix: { (l3benchmark) \c_space_tl + \prg_replicate:nn { \g__benchmark_tictoc_int } { -+ } \c_space_tl } \cs_new_protected:Npn \benchmark_tic: { \iow_term:e { \__benchmark_tictoc_prefix: TIC } \exp_args:NNf \seq_gput_right:Nn \g__benchmark_tictoc_seq { \sys_timer: } \int_gincr:N \g__benchmark_tictoc_int } \cs_new:Npn \benchmark_toc: { \seq_gpop_right:NNTF \g__benchmark_tictoc_seq \l__benchmark_tictoc_pop_tl { \__benchmark_toc: } { \msg_error:nn { benchmark } { toc-first } } } \cs_new_protected:Npn \__benchmark_toc: { \int_gdecr:N \g__benchmark_tictoc_int \fp_gset:Nn \g_benchmark_time_fp { ( \sys_timer: - \l__benchmark_tictoc_pop_tl ) / 65536 } \iow_term:e { \__benchmark_tictoc_prefix: TOC: \c_space_tl \__benchmark_fp_to_tl:N \g_benchmark_time_fp \c_space_tl s } } \msg_new:nnn { benchmark } { toc-first } { \token_to_str:N \benchmark_toc: \c_space_tl without~ \token_to_str:N \benchmark_tic: \c_space_tl ! } %% %% %% End of file `l3benchmark.sty'.