You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
9.1 KiB
269 lines
9.1 KiB
%%
|
|
%% This is file `l3benchmark.sty',
|
|
%% generated with the docstrip utility.
|
|
%%
|
|
%% The original source files were:
|
|
%%
|
|
%% l3benchmark.dtx (with options: `package')
|
|
%%
|
|
%% Copyright (C) 2018-2020 The LaTeX3 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}{2020-08-07}{}
|
|
{L3 Experimental benchmarking}
|
|
\sys_if_engine_luatex:TF
|
|
{
|
|
\cs_new:Npn \sys_timer:
|
|
{ \lua_now:n { l3kernel.elapsedtime() } }
|
|
}
|
|
{
|
|
\cs_if_exist:NT \tex_elapsedtime:D
|
|
{
|
|
\cs_new:Npn \sys_timer:
|
|
{ \int_value:w \tex_elapsedtime:D }
|
|
}
|
|
}
|
|
\__sys_const:nn { sys_if_timer_exist }
|
|
{ \cs_if_exist_p:N \sys_timer: }
|
|
\cs_if_exist:NTF \sys_timer:
|
|
{
|
|
\sys_if_engine_luatex:TF
|
|
{
|
|
\cs_new_protected:Npn \sys_gzero_timer:
|
|
{ \lua_now:n { l3kernel.resettimer() } }
|
|
}
|
|
{ \cs_new_protected:Npn \sys_gzero_timer: { \tex_resettimer:D } }
|
|
}
|
|
{
|
|
\__kernel_msg_new:nnnn { kernel } { no-elapsed-time }
|
|
{ No~clock~detected~for~#1. }
|
|
{ The~current~engine~provides~no~way~to~access~the~system~time. }
|
|
\cs_new_protected:Npn \sys_gzero_timer:
|
|
{
|
|
\__kernel_msg_error:nnn { kernel } { no-elapsed-time }
|
|
{ \sys_gzero_timer: }
|
|
}
|
|
\cs_new:Npn \sys_timer:
|
|
{
|
|
\int_value:w
|
|
\__kernel_msg_expandable_error:nnn { kernel } { no-elapsed-time }
|
|
{ \sys_timer: }
|
|
\c_zero_int
|
|
}
|
|
}
|
|
\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_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:Npx \__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:Npx \__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_measure_op:
|
|
\__benchmark_raw:nN {#1} \g__benchmark_time_int
|
|
\fp_gset:Nn \g__benchmark_time_fp { \g__benchmark_time_int / 65536 }
|
|
\__benchmark_display:
|
|
}
|
|
\cs_new_protected:Npn \benchmark:n #1
|
|
{
|
|
\__benchmark_measure_op:
|
|
\tl_gset:Nn \g__benchmark_code_tl {#1}
|
|
\__benchmark_aux:
|
|
\__benchmark_display:
|
|
}
|
|
\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-16) }
|
|
\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:
|
|
{
|
|
\fp_gset:Nn \g__benchmark_ops_fp { \g__benchmark_time_fp / \g__benchmark_one_op_fp }
|
|
\iow_term:x
|
|
{
|
|
\__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:x { \__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:x
|
|
{
|
|
\__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'.
|
|
|