interpreter_benchmarks.ml
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2021-2022 Nomadic Labs <contact@nomadic-labs.com> *)
(* Copyright (c) 2022 DaiLambda, Inc. <contact@dailambda,jp> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
let ns = Interpreter_model.ns
let fv = Interpreter_model.fv
module Timelock_samplers = Tezos_crypto.Timelock
open Protocol
(* ------------------------------------------------------------------------- *)
type ex_stack_and_kinstr =
| Ex_stack_and_kinstr : {
stack : 'a * 'b;
stack_type : ('a, 'b) Script_typed_ir.stack_ty;
kinstr : ('a, 'b, 'c, 'd) Script_typed_ir.kinstr;
}
-> ex_stack_and_kinstr
type ex_stack_and_continuation =
| Ex_stack_and_cont : {
stack : 'a * 'b;
stack_type : ('a, 'b) Script_typed_ir.stack_ty;
cont : ('a, 'b, 'c, 'd) Script_typed_ir.continuation;
}
-> ex_stack_and_continuation
type ex_value =
| Ex_value : {value : 'a; ty : ('a, _) Script_typed_ir.ty} -> ex_value
(* ------------------------------------------------------------------------- *)
let sf = Printf.sprintf
(* End of Stack *)
let eos = Script_typed_ir.(EmptyCell, EmptyCell)
let info_and_name ~intercept ?(salt = "") s =
let s = s ^ salt in
if intercept then
(sf "Benchmark %s (intercept case)" s, Namespace.make ns s "intercept")
else (sf "Benchmark %s" s, ns s)
module Default_boilerplate = struct
type workload = Interpreter_workload.t
let workload_encoding = Interpreter_workload.encoding
let workload_to_vector = Interpreter_workload.trace_to_sparse_vec
let tags = [Tags.interpreter]
end
module Default_config = struct
(* Configuration specific to sapling benchmarks *)
type sapling_config = {sapling_txs_file : string; seed : int option}
(* Configuration specific to benchmarking Dign/Dipn/Dupn/Dropn/Combs *)
type comb_config = {max_depth : int}
(* Configuration specific to benchmarking ICompare *)
type compare_config = {type_size : Base_samplers.range}
type config = {
sampler : Michelson_samplers.parameters;
sapling : sapling_config;
comb : comb_config;
compare : compare_config;
}
let default_config =
let open Michelson_samplers in
let open Michelson_samplers_base in
let sampler =
{
base_parameters =
{
int_size = {min = 8; max = 100_000};
string_size = {min = 1 lsl 10; max = 1 lsl 17};
bytes_size = {min = 1 lsl 10; max = 1 lsl 17};
};
list_size = {min = 10; max = 1000};
set_size = {min = 10; max = 1000};
map_size = {min = 10; max = 1000};
}
in
{
sampler;
sapling = {sapling_txs_file = {|/no/such/file|}; seed = None};
comb = {max_depth = 1000};
compare = {type_size = {min = 1; max = 15}};
}
let sapling_config_encoding =
let open Data_encoding in
conv
(fun {sapling_txs_file; seed} -> (sapling_txs_file, seed))
(fun (sapling_txs_file, seed) -> {sapling_txs_file; seed})
(obj2 (req "sapling_txs_file" string) (req "seed" (option int31)))
let comb_config_encoding =
let open Data_encoding in
conv
(fun {max_depth} -> max_depth)
(fun max_depth -> {max_depth})
(obj1 (req "max_depth" int31))
let compare_config_encoding =
let open Data_encoding in
conv
(fun {type_size} -> type_size)
(fun type_size -> {type_size})
(obj1 (req "type_size" Base_samplers.range_encoding))
let config_encoding =
let open Data_encoding in
conv
(fun {sampler; sapling; comb; compare} ->
(sampler, sapling, comb, compare))
(fun (sampler, sapling, comb, compare) ->
{sampler; sapling; comb; compare})
(obj4
(req "sampler" Michelson_samplers.parameters_encoding)
(req "sapling" sapling_config_encoding)
(req "comb" comb_config_encoding)
(req "compare" compare_config_encoding))
end
let make_default_samplers ?(algo = `Default) cfg :
(module Crypto_samplers.Finite_key_pool_S) * (module Michelson_samplers.S) =
let module Crypto_samplers = Crypto_samplers.Make_finite_key_pool (struct
let size = 16
let algo = algo
end) in
let module Michelson_samplers =
Michelson_samplers.Make
(struct
let parameters = cfg
end)
(Crypto_samplers)
in
((module Crypto_samplers), (module Michelson_samplers))
(* ------------------------------------------------------------------------- *)
(* Helpers for creating benchmarks for the interpreter *)
let benchmark_from_kinstr_and_stack :
?amplification:int ->
Alpha_context.context ->
Protocol.Script_interpreter.step_constants ->
ex_stack_and_kinstr ->
Interpreter_workload.ir_sized_step list Generator.benchmark =
fun ?amplification ctxt step_constants stack_kinstr ->
let ctxt = Gas_helpers.set_limit ctxt in
let measure_allocation ~outdated_ctxt ~step_constants ~kinstr ~bef_top ~bef ()
=
let result =
Lwt_main.run
@@ Script_interpreter.Internals.step
(outdated_ctxt, step_constants)
(Local_gas_counter 9_999_999_999)
kinstr
bef_top
bef
in
Option.map (fun (stack_top, stack, _, _) ->
let size_after =
Obj.reachable_words (Obj.repr (stack_top, stack, bef_top, bef))
in
let size_before =
Obj.reachable_words (Obj.repr (bef_top, bef, bef_top, bef))
in
size_after - size_before)
@@ Result.to_option result
in
match stack_kinstr with
| Ex_stack_and_kinstr {stack = bef_top, bef; stack_type; kinstr} ->
let workload, closure, measure_allocation =
match amplification with
| None ->
let workload =
Interpreter_workload.extract_deps
ctxt
step_constants
stack_type
kinstr
(bef_top, bef)
in
let _gas_counter, outdated_ctxt =
Local_gas_counter.local_gas_counter_and_outdated_context ctxt
in
let closure () =
(* Lwt_main.run *)
ignore
(Script_interpreter.Internals.step
(outdated_ctxt, step_constants)
(Local_gas_counter 9_999_999_999)
kinstr
bef_top
bef)
in
let measure_allocation =
measure_allocation
~outdated_ctxt
~step_constants
~kinstr
~bef_top
~bef
in
(workload, closure, measure_allocation)
| Some amplification_factor ->
assert (amplification_factor > 0) ;
let workload =
Interpreter_workload.extract_deps
ctxt
step_constants
stack_type
kinstr
(bef_top, bef)
in
let workload =
List.repeat amplification_factor workload |> List.flatten
in
let _gas_counter, outdated_ctxt =
Local_gas_counter.local_gas_counter_and_outdated_context ctxt
in
let closure () =
for _i = 1 to amplification_factor do
ignore
(* Lwt_main.run *)
(Script_interpreter.Internals.step
(outdated_ctxt, step_constants)
(Local_gas_counter 9_999_999_999)
kinstr
bef_top
bef)
done
in
let measure_allocation =
measure_allocation
~outdated_ctxt
~step_constants
~kinstr
~bef_top
~bef
in
(workload, closure, measure_allocation)
in
Generator.PlainWithAllocation {workload; closure; measure_allocation}
let make_benchmark :
?amplification:int ->
?intercept:bool ->
?salt:string ->
?more_tags:string list ->
?check:(unit -> unit) ->
name:Interpreter_workload.instruction_name ->
kinstr_and_stack_sampler:
(Default_config.config -> Random.State.t -> unit -> ex_stack_and_kinstr) ->
unit ->
Benchmark.t =
fun ?amplification
?(intercept = false)
?salt
?(more_tags = [])
?(check = fun () -> ())
~name
~kinstr_and_stack_sampler
() ->
let module B : Benchmark.S = struct
include Default_config
include Default_boilerplate
let tags = tags @ more_tags
let models =
(* [intercept = true] implies there's a benchmark with [intercept = false].
No need to register the model twice. *)
Interpreter_model.make_model ?amplification (Instr_name name)
let info, name =
info_and_name
~intercept
?salt
(Interpreter_workload.string_of_instruction_name name)
let module_filename = __FILE__
let generated_code_destination = None
let benchmark kinstr_and_stack_sampler ctxt step_constants () =
let stack_instr = kinstr_and_stack_sampler () in
benchmark_from_kinstr_and_stack
?amplification
ctxt
step_constants
stack_instr
let create_benchmarks ~rng_state ~bench_num (config : config) =
check () ;
match Lwt_main.run (Execution_context.make ~rng_state) with
| Error _errs -> assert false
| Ok (ctxt, step_constants) ->
let kinstr_and_stack_sampler =
kinstr_and_stack_sampler config rng_state
in
List.repeat
bench_num
(benchmark kinstr_and_stack_sampler ctxt step_constants)
end in
(module B : Benchmark.S)
let make_simple_benchmark :
type bef_top bef res_top res.
?amplification:int ->
?intercept:bool ->
?more_tags:string list ->
?salt:string ->
?check:(unit -> unit) ->
name:Interpreter_workload.instruction_name ->
stack_type:(bef_top, bef) Script_typed_ir.stack_ty ->
kinstr:(bef_top, bef, res_top, res) Script_typed_ir.kinstr ->
unit ->
Benchmark.t =
fun ?amplification
?intercept
?more_tags
?salt
?check
~name
~stack_type
~kinstr
() ->
let kinstr_and_stack_sampler config rng_state =
let _, (module Samplers) =
make_default_samplers config.Default_config.sampler
in
fun () ->
Ex_stack_and_kinstr
{
stack = Samplers.Random_value.stack stack_type rng_state;
stack_type;
kinstr;
}
in
make_benchmark
?amplification
?intercept
?more_tags
?salt
?check
~name
~kinstr_and_stack_sampler
()
let benchmark ?amplification ?intercept ?more_tags ?salt ?check ~name
~kinstr_and_stack_sampler () =
let bench =
make_benchmark
?amplification
?intercept
?more_tags
?salt
?check
~name
~kinstr_and_stack_sampler
()
in
Registration_helpers.register bench
let benchmark_with_stack_sampler ?amplification ?intercept ?more_tags ?salt
?check ~stack_type ~name ~kinstr ~stack_sampler () =
let kinstr_and_stack_sampler config rng_state =
let stack_sampler = stack_sampler config rng_state in
fun () -> Ex_stack_and_kinstr {stack = stack_sampler (); stack_type; kinstr}
in
let bench =
make_benchmark
?amplification
?intercept
?more_tags
?salt
?check
~name
~kinstr_and_stack_sampler
()
in
Registration_helpers.register bench
let benchmark_with_fixed_stack ?amplification ?intercept ?more_tags ?salt ?check
~name ~stack ~kinstr () =
benchmark_with_stack_sampler
?amplification
?intercept
?more_tags
?salt
?check
~name
~kinstr
~stack_sampler:(fun _cfg _rng_state () -> stack)
()
let simple_benchmark_with_stack_sampler ?amplification ?intercept_stack ?salt
?more_tags ?check ~name ~stack_type ~kinstr ~stack_sampler () =
benchmark_with_stack_sampler
?amplification
~intercept:false
?salt
?more_tags
?check
~name
~stack_type
~kinstr
~stack_sampler
() ;
Option.iter
(fun stack ->
benchmark_with_fixed_stack
?amplification
~intercept:true
?more_tags
?salt
?check
~name
~stack_type
~stack
~kinstr
())
intercept_stack
let simple_benchmark ?amplification ?intercept_stack ?more_tags ?salt ?check
~name ~stack_type ~kinstr () =
let bench =
make_simple_benchmark
?amplification
~intercept:false
?more_tags
?salt
?check
~name
~stack_type
~kinstr
()
in
Registration_helpers.register bench ;
Option.iter
(fun stack ->
benchmark_with_fixed_stack
?amplification
~intercept:true
?more_tags
?salt
?check
~name
~stack_type
~stack
~kinstr
())
intercept_stack
(* ------------------------------------------------------------------------- *)
(* Helpers for creating benchmarks for [Script_interpreter.next] *)
let benchmark_from_continuation :
?amplification:int ->
Alpha_context.context ->
Protocol.Script_interpreter.step_constants ->
ex_stack_and_continuation ->
Interpreter_workload.ir_sized_step list Generator.benchmark =
fun ?amplification ctxt step_constants stack_cont ->
let ctxt = Gas_helpers.set_limit ctxt in
match stack_cont with
| Ex_stack_and_cont {stack = bef_top, bef; cont; stack_type} ->
let workload, closure =
match amplification with
| None ->
let workload =
Interpreter_workload.extract_deps_continuation
ctxt
step_constants
stack_type
cont
(bef_top, bef)
in
let _gas_counter, outdated_ctxt =
Local_gas_counter.local_gas_counter_and_outdated_context ctxt
in
let closure () =
ignore
(* Lwt_main.run *)
(Script_interpreter.Internals.next
None
(outdated_ctxt, step_constants)
(Local_gas_counter 9_999_999_999)
stack_type
cont
bef_top
bef)
in
(workload, closure)
| Some amplification_factor ->
assert (amplification_factor > 0) ;
let workload =
Interpreter_workload.extract_deps_continuation
ctxt
step_constants
stack_type
cont
(bef_top, bef)
in
let workload =
List.repeat amplification_factor workload |> List.flatten
in
let _gas_counter, outdated_ctxt =
Local_gas_counter.local_gas_counter_and_outdated_context ctxt
in
let closure () =
for _i = 1 to amplification_factor do
ignore
(* Lwt_main.run *)
(Script_interpreter.Internals.next
None
(outdated_ctxt, step_constants)
(Local_gas_counter 9_999_999_999)
stack_type
cont
bef_top
bef)
done
in
(workload, closure)
in
Generator.Plain {workload; closure}
let make_continuation_benchmark :
?amplification:int ->
?intercept:bool ->
?salt:string ->
?more_tags:string list ->
?check:(unit -> unit) ->
name:Interpreter_workload.continuation_name ->
cont_and_stack_sampler:
(Default_config.config ->
Random.State.t ->
unit ->
ex_stack_and_continuation) ->
unit ->
Benchmark.t =
fun ?amplification
?(intercept = false)
?salt
?(more_tags = [])
?(check = fun () -> ())
~name
~cont_and_stack_sampler
() ->
let module B : Benchmark.S = struct
include Default_config
include Default_boilerplate
let tags = tags @ more_tags
let models = Interpreter_model.make_model ?amplification (Cont_name name)
let info, name =
info_and_name
~intercept
?salt
(Interpreter_workload.string_of_continuation_name name)
let module_filename = __FILE__
let generated_code_destination = None
let benchmark cont_and_stack_sampler ctxt step_constants () =
let stack_instr = cont_and_stack_sampler () in
benchmark_from_continuation ?amplification ctxt step_constants stack_instr
let create_benchmarks ~rng_state ~bench_num (config : config) =
check () ;
match Lwt_main.run (Execution_context.make ~rng_state) with
| Error _errs -> assert false
| Ok (ctxt, step_constants) ->
let cont_and_stack_sampler =
cont_and_stack_sampler config rng_state
in
List.repeat
bench_num
(benchmark cont_and_stack_sampler ctxt step_constants)
end in
(module B : Benchmark.S)
let continuation_benchmark ?amplification ?intercept ?salt ?more_tags ?check
~name ~cont_and_stack_sampler () =
let bench =
make_continuation_benchmark
?amplification
?intercept
?salt
?more_tags
?check
~name
~cont_and_stack_sampler
()
in
Registration_helpers.register bench
(* ------------------------------------------------------------------------- *)
(* Sampling helpers *)
let nat_of_positive_int (i : int) =
let open Script_int in
match is_nat (of_int i) with None -> assert false | Some x -> x
let adversarial_ints rng_state (cfg : Default_config.config) n =
let _common_prefix, ls =
Base_samplers.Adversarial.integers
~prefix_size:cfg.sampler.base_parameters.int_size
~card:n
rng_state
in
List.map Script_int.of_zint ls
(* ------------------------------------------------------------------------- *)
(* Error helpers *)
let raise_if_error = function
| Ok x -> x
| Error e ->
Format.eprintf "%a@." (Error_monad.TzTrace.pp_print Error_monad.pp) e ;
Stdlib.failwith "raise_if_error"
(* ------------------------------------------------------------------------- *)
(** [Registration_section] contains all interpreter benchmarks. The goal of
a benchmark is to gather enough data to reliably estimate the parameters
of the cost model associated to each instruction. In general, it can
take several distinct benchmarks to properly cover all the execution
paths.
In particular, for affine cost model, it is often worth estimating the
intercept separately from the size-dependent coefficients.
*)
module Registration_section = struct
open Script_typed_ir
open Michelson_types
let sf = Printf.sprintf
let dummy_loc = 0
let halt = IHalt dummy_loc
let () =
(* KHalt *)
simple_benchmark
~amplification:100
~name:Interpreter_workload.N_IHalt
~stack_type:(unit @$ bot)
~kinstr:halt
()
module Amplification = struct
module Loop : Benchmark.S = struct
let name = ns "amplification_loop"
let info = "Benchmarking the cost of an empty loop"
let module_filename = __FILE__
let generated_code_destination = None
let tags = [Tags.interpreter]
type config = {max_iterations : int}
let config_encoding =
let open Data_encoding in
conv
(fun {max_iterations} -> max_iterations)
(fun max_iterations -> {max_iterations})
(obj1 (req "max_iterations" int31))
let default_config = {max_iterations = 100000}
type workload = int
let workload_encoding = Data_encoding.int31
let workload_to_vector n =
Sparse_vec.String.of_list [("iterations", float_of_int n)]
let models = [("interpreter", Interpreter_model.amplification_loop_model)]
let benchmark rng_state config () =
let workload = Random.State.int rng_state config.max_iterations in
let closure () =
for _i = 1 to workload do
Sys.opaque_identity ()
done
in
Generator.Plain {workload; closure}
let create_benchmarks ~rng_state ~bench_num (config : config) =
List.repeat bench_num (benchmark rng_state config)
end
end
let () = Registration_helpers.register (module Amplification.Loop)
module Stack = struct
let () =
(* KDrop ; KHalt *)
simple_benchmark
~amplification:100
~name:Interpreter_workload.N_IDrop
~stack_type:(unit @$ unit @$ bot)
~kinstr:(IDrop (dummy_loc, halt))
()
let () =
(* IDup ; IHalt *)
simple_benchmark
~amplification:100
~name:Interpreter_workload.N_IDup
~stack_type:(unit @$ unit @$ bot)
~kinstr:(IDup (dummy_loc, halt))
()
let () =
simple_benchmark
~amplification:100
~name:Interpreter_workload.N_ISwap
~stack_type:(unit @$ unit @$ bot)
~kinstr:(ISwap (dummy_loc, halt))
()
let () =
simple_benchmark
~amplification:100
~name:Interpreter_workload.N_IPush
~stack_type:(unit @$ unit @$ bot)
~kinstr:(IPush (dummy_loc, unit, (), halt))
()
let () =
simple_benchmark
~amplification:100
~name:Interpreter_workload.N_IUnit
~stack_type:(unit @$ unit @$ bot)
~kinstr:(IUnit (dummy_loc, halt))
()
(* deep stack manipulation *)
(* Constructing these instructions is made especially painful by the
fact that they include "stack preservation witnesses", which are not
exposed in Script_ir_translator.
We must go through [Script_ir_translator.parse_instr] to construct
the corresponding terms. *)
type ex_stack =
| Ex_stack : ('a, 'b) Script_typed_ir.stack_ty * ('a * 'b) -> ex_stack
let rec make_stack (depth : int) =
if depth = 0 then assert false
else if depth = 1 then Ex_stack (unit @$ Script_typed_ir.Bot_t, ((), eos))
else
let stack = make_stack (depth - 1) in
match stack with
| Ex_stack (stack_ty, stack) -> Ex_stack (unit @$ stack_ty, ((), stack))
let parse_instr rng_state node stack =
match stack with
| Ex_stack (stack_ty, stack) ->
raise_if_error
(Lwt_main.run
( Execution_context.make ~rng_state
>>=? fun (ctxt, _step_constants) ->
Script_ir_translator.parse_instr
Script_tc_context.data
ctxt
~elab_conf:
(Script_ir_translator_config.make ~legacy:false ())
node
stack_ty
>|= Environment.wrap_tzresult
>>=? fun (judgement, _) ->
match judgement with
| Script_ir_translator.Typed descr ->
let kinstr = descr.instr.apply (IHalt dummy_loc) in
return
(Ex_stack_and_kinstr
{stack; kinstr; stack_type = descr.bef})
| Script_ir_translator.Failed _ -> assert false ))
open Protocol.Michelson_v1_primitives
(* The size parameter of a deep stack instruction must fit on 10 bits. See
[Script_ir_translator.parse_uint10]. *)
let stack_size = 1023
let long_stack = make_stack stack_size
let sample_depth rng_state =
Base_samplers.(
sample_in_interval rng_state ~range:{min = 0; max = stack_size - 2})
let () =
let dig = Micheline.(Prim (0, I_DIG, [Int (0, Z.of_int 0)], [])) in
benchmark
~amplification:100
~intercept:true
~name:Interpreter_workload.N_IDig
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dig in
parse_instr rng_state node long_stack)
()
let () =
let dig n = Micheline.(Prim (0, I_DIG, [Int (0, Z.of_int n)], [])) in
benchmark
~name:Interpreter_workload.N_IDig
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dig (sample_depth rng_state) in
parse_instr rng_state node long_stack)
()
let () =
let dug = Micheline.(Prim (0, I_DUG, [Int (0, Z.of_int 0)], [])) in
benchmark
~intercept:true
~name:Interpreter_workload.N_IDug
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dug in
parse_instr rng_state node long_stack)
()
let () =
let dug n = Micheline.(Prim (0, I_DUG, [Int (0, Z.of_int n)], [])) in
benchmark
~name:Interpreter_workload.N_IDug
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dug (sample_depth rng_state) in
parse_instr rng_state node long_stack)
()
let () =
let nop = Micheline.Seq (0, []) in
let dip = Micheline.(Prim (0, I_DIP, [Int (0, Z.of_int 0); nop], [])) in
benchmark
~intercept:true
~name:Interpreter_workload.N_IDipN
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dip in
parse_instr rng_state node long_stack)
()
let () =
let nop = Micheline.Seq (0, []) in
let dip n = Micheline.(Prim (0, I_DIP, [Int (0, Z.of_int n); nop], [])) in
benchmark
~name:Interpreter_workload.N_IDipN
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dip (sample_depth rng_state) in
parse_instr rng_state node long_stack)
()
let () =
let drop = Micheline.(Prim (0, I_DROP, [Int (0, Z.of_int 0)], [])) in
benchmark
~intercept:true
~name:Interpreter_workload.N_IDropN
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = drop in
parse_instr rng_state node long_stack)
()
let () =
let drop n = Micheline.(Prim (0, I_DROP, [Int (0, Z.of_int n)], [])) in
benchmark
~name:Interpreter_workload.N_IDropN
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = drop (sample_depth rng_state) in
parse_instr rng_state node long_stack)
()
let () =
let pair n = Micheline.(Prim (0, I_PAIR, [Int (0, Z.of_int n)], [])) in
benchmark
~name:Interpreter_workload.N_IComb
~kinstr_and_stack_sampler:(fun cfg rng_state () ->
let width =
Base_samplers.(
sample_in_interval
rng_state
~range:{min = 2; max = cfg.comb.max_depth})
in
let node = pair width in
parse_instr rng_state node long_stack)
()
let rec make_comb_stack (comb_width : int) (depth : int) acc =
if depth = 0 then
match acc with
| Ex_stack (stack_ty, stack) -> (
match make_comb comb_width (Ex_value {value = (); ty = unit}) with
| Ex_value {value; ty} -> Ex_stack (ty @$ stack_ty, (value, stack)))
else
match acc with
| Ex_stack (stack_ty, stack) ->
make_comb_stack
comb_width
(depth - 1)
(Ex_stack (unit @$ stack_ty, ((), stack)))
and make_comb comb_width comb_acc =
if comb_width = 0 then assert false
else if comb_width = 1 then comb_acc
else
match comb_acc with
| Ex_value {value; ty} ->
let (Ty_ex_c ty) = pair unit ty in
make_comb (comb_width - 1) (Ex_value {value = ((), value); ty})
let () =
let unpair n =
Micheline.(Prim (0, I_UNPAIR, [Int (0, Z.of_int n)], []))
in
benchmark
~name:Interpreter_workload.N_IUncomb
~kinstr_and_stack_sampler:(fun cfg rng_state () ->
let width =
Base_samplers.(
sample_in_interval
rng_state
~range:{min = 2; max = cfg.comb.max_depth - 2})
in
let node = unpair width in
let stack =
make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos)))
in
parse_instr rng_state node stack)
()
let () =
let comb_get n = Micheline.(Prim (0, I_GET, [Int (0, Z.of_int n)], [])) in
benchmark
~name:Interpreter_workload.N_IComb_get
~kinstr_and_stack_sampler:(fun cfg rng_state () ->
let width =
Base_samplers.(
sample_in_interval
rng_state
~range:{min = 2; max = cfg.comb.max_depth - 2})
in
let index =
Base_samplers.(
sample_in_interval rng_state ~range:{min = 0; max = width})
in
let node = comb_get index in
let stack =
make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos)))
in
parse_instr rng_state node stack)
()
let () =
let comb_set n =
Micheline.(Prim (0, I_UPDATE, [Int (0, Z.of_int n)], []))
in
benchmark
~name:Interpreter_workload.N_IComb_set
~kinstr_and_stack_sampler:(fun cfg rng_state () ->
let width =
Base_samplers.(
sample_in_interval
rng_state
~range:{min = 2; max = cfg.comb.max_depth - 2})
in
let index =
Base_samplers.(
sample_in_interval rng_state ~range:{min = 0; max = width})
in
let node = comb_set index in
let stack =
let (Ex_stack (stack_ty, stack)) =
make_comb_stack width 1 (Ex_stack (unit @$ bot, ((), eos)))
in
Ex_stack (unit @$ stack_ty, ((), stack))
in
parse_instr rng_state node stack)
()
let () =
let dup n = Micheline.(Prim (0, I_DUP, [Int (0, Z.of_int n)], [])) in
benchmark
~name:Interpreter_workload.N_IDupN
~kinstr_and_stack_sampler:(fun _cfg rng_state () ->
let node = dup (1 + sample_depth rng_state) in
parse_instr rng_state node long_stack)
()
end
module Pairs = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_ICons_pair
~stack_type:(unit @$ unit @$ bot)
~kinstr:(ICons_pair (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ICar
~stack_type:(cpair unit unit @$ bot)
~kinstr:(ICar (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ICdr
~stack_type:(cpair unit unit @$ bot)
~kinstr:(ICdr (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IUnpair
~stack_type:(cpair unit unit @$ bot)
~kinstr:(IUnpair (dummy_loc, halt))
()
end
module Options = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_ICons_some
~stack_type:(unit @$ bot)
~kinstr:(ICons_some (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ICons_none
~stack_type:(unit @$ bot)
~kinstr:(ICons_none (dummy_loc, unit, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IIf_none
~stack_type:(option unit @$ bot)
~kinstr:
(IIf_none
{
loc = dummy_loc;
branch_if_none = halt;
branch_if_some = IDrop (dummy_loc, halt);
k = halt;
})
()
let () =
benchmark_with_fixed_stack
~name:Interpreter_workload.N_IOpt_map
~salt:"none"
~stack:(None, ((), eos))
~stack_type:(option unit @$ unit @$ bot)
~kinstr:(IOpt_map {loc = dummy_loc; body = halt; k = halt})
()
let () =
benchmark_with_fixed_stack
~name:Interpreter_workload.N_IOpt_map
~salt:"some"
~stack:(Some (), ((), eos))
~stack_type:(option unit @$ unit @$ bot)
~kinstr:(IOpt_map {loc = dummy_loc; body = halt; k = halt})
()
end
module Ors = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_ILeft
~stack_type:(unit @$ bot)
~kinstr:(ICons_left (dummy_loc, unit, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IRight
~stack_type:(unit @$ bot)
~kinstr:(ICons_right (dummy_loc, unit, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IIf_left
~stack_type:(cor unit unit @$ bot)
~kinstr:
(IIf_left
{
loc = dummy_loc;
branch_if_left = halt;
branch_if_right = halt;
k = halt;
})
()
end
module Lists = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_ICons_list
~stack_type:(unit @$ list unit @$ bot)
~kinstr:(ICons_list (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INil
~stack_type:(unit @$ bot)
~kinstr:(INil (dummy_loc, unit, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IIf_cons
~stack_type:(list unit @$ unit @$ bot)
~kinstr:
(IIf_cons
{
loc = dummy_loc;
branch_if_cons = IDrop (dummy_loc, IDrop (dummy_loc, halt));
branch_if_nil = halt;
k = halt;
})
()
module Mapping = struct
let () =
(*
IList_map ->
IList_enter_body (empty case) ->
IHalt
*)
benchmark_with_fixed_stack
~name:Interpreter_workload.N_IList_map
~stack:(Script_list.empty, ((), eos))
~stack_type:(list unit @$ unit @$ bot)
~kinstr:(IList_map (dummy_loc, halt, Some (list unit), halt))
()
end
let () =
simple_benchmark
~name:Interpreter_workload.N_IList_size
~stack_type:(list unit @$ bot)
~kinstr:(IList_size (dummy_loc, halt))
()
let () =
(*
IList_iter ->
IIter (empty case) ->
IHalt
*)
benchmark_with_fixed_stack
~name:Interpreter_workload.N_IList_iter
~stack:(Script_list.empty, ((), eos))
~stack_type:(list unit @$ unit @$ bot)
~kinstr:
(IList_iter (dummy_loc, Some unit, IDrop (dummy_loc, halt), halt))
()
end
module Sets = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_IEmpty_set
~stack_type:(unit @$ bot)
~kinstr:(IEmpty_set (dummy_loc, unit, halt))
()
let set_iter_code =
ISet_iter (dummy_loc, Some int, IDrop (dummy_loc, halt), halt)
let () =
(*
ISet_iter ->
(List.rev (set_fold)) ->
{
IIter ->
IDrop ->
ICons ->
...
}
*)
simple_benchmark
~name:Interpreter_workload.N_ISet_iter
~intercept_stack:(Script_set.empty int, ((), eos))
~stack_type:(set int @$ unit @$ bot)
~kinstr:set_iter_code
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ISet_mem
~stack_type:(int @$ set int @$ unit @$ bot)
~kinstr:(ISet_mem (dummy_loc, halt))
~intercept_stack:(Script_int.zero, (Script_set.empty int, ((), eos)))
~stack_sampler:(fun cfg rng_state () ->
assert (cfg.sampler.set_size.min >= 1) ;
let n =
Base_samplers.sample_in_interval
rng_state
~range:cfg.sampler.set_size
in
let elts = adversarial_ints rng_state cfg n in
let set =
List.fold_left
(fun set elt -> Script_set.update elt true set)
(Script_set.empty int)
elts
in
let elt =
List.nth_opt elts (Random.State.int rng_state n)
|> WithExceptions.Option.get ~loc:__LOC__
in
(elt, (set, ((), eos))))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ISet_update
~stack_type:(int @$ bool @$ set int @$ bot)
~kinstr:(ISet_update (dummy_loc, halt))
~intercept_stack:(Script_int.zero, (false, (Script_set.empty int, eos)))
~stack_sampler:(fun cfg rng_state () ->
assert (cfg.sampler.set_size.min >= 2) ;
let n =
Base_samplers.sample_in_interval
rng_state
~range:cfg.sampler.set_size
in
let elts = adversarial_ints rng_state cfg (n + 1) in
let out_of_set, in_set =
match elts with [] -> assert false | hd :: tl -> (hd, tl)
in
let set =
List.fold_left
(fun set elt -> Script_set.update elt true set)
(Script_set.empty int)
in_set
in
let stack =
let flip = Random.State.bool rng_state in
if flip then
(* add an element not in the set *)
(out_of_set, (true, (set, eos)))
else
(* remove an element in the set *)
let elt = out_of_set in
let set = Script_set.update elt true set in
(elt, (flip, (set, eos)))
in
stack)
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISet_size
~stack_type:(set unit @$ bot)
~kinstr:(ISet_size (dummy_loc, halt))
()
end
module Maps = struct
let generate_map_and_key_in_map (cfg : Default_config.config) rng_state =
let n =
Base_samplers.sample_in_interval rng_state ~range:cfg.sampler.set_size
in
let keys = adversarial_ints rng_state cfg n in
let map =
List.fold_left
(fun map i -> Script_map.update i (Some ()) map)
(Script_map.empty int)
keys
in
let (module M) = Script_map.get_module map in
let key =
M.OPS.fold (fun k _ -> function None -> Some k | x -> x) M.boxed None
|> WithExceptions.Option.get ~loc:__LOC__
in
(key, map)
let () =
simple_benchmark
~name:Interpreter_workload.N_IEmpty_map
~stack_type:(unit @$ bot)
~kinstr:(IEmpty_map (dummy_loc, unit, Some unit, halt))
()
(*
let map_map_code =
IMap_map
( dummy_loc,
ICdr (dummy_loc, halt_unitunit),
halt )
*)
let map_map_code () =
IMap_map
( dummy_loc,
Some (map int unit),
IFailwith (dummy_loc, cpair int unit),
halt )
let () =
(*
Map_map (nonempty case) ->
(List.rev (map_fold nonempty_map)) ->
KMap_enter_body (nonempty case) ->
fail (early interruption)
*)
simple_benchmark
~name:Interpreter_workload.N_IMap_map
~intercept_stack:
(let map = Script_map.empty int in
(map, ((), eos)))
~stack_type:(map int unit @$ unit @$ bot)
~kinstr:(map_map_code ())
()
let kmap_iter_code =
IMap_iter (dummy_loc, Some (cpair int unit), IDrop (dummy_loc, halt), halt)
let () =
(*
IMap_iter (nonempty case) ->
(List.rev (map_fold (nonempty))) ->
IIter (nonempty case) ->
...
*)
simple_benchmark
~name:Interpreter_workload.N_IMap_iter
~intercept_stack:
(let map = Script_map.empty int in
(map, ((), eos)))
~stack_type:(map int unit @$ unit @$ bot)
~kinstr:kmap_iter_code
()
let () =
(*
IMap_mem ->
(map_mem) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMap_mem
~stack_type:(int @$ map int unit @$ unit @$ bot)
~kinstr:(IMap_mem (dummy_loc, halt))
~intercept_stack:
(let map = Script_map.empty int in
(Script_int.zero, (map, ((), eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_map_and_key_in_map cfg rng_state in
(key, (map, ((), eos))))
()
let () =
(*
IMap_get ->
(map_get) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMap_get
~stack_type:(int @$ map int unit @$ unit @$ bot)
~kinstr:(IMap_get (dummy_loc, halt))
~intercept_stack:
(let map = Script_map.empty int in
(Script_int.zero, (map, ((), eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_map_and_key_in_map cfg rng_state in
(key, (map, ((), eos))))
()
let () =
(*
IMap_update ->
(map_update) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMap_update
~stack_type:(int @$ option unit @$ map int unit @$ bot)
~kinstr:(IMap_update (dummy_loc, halt))
~intercept_stack:
(let map = Script_map.empty int in
(Script_int.zero, (None, (map, eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_map_and_key_in_map cfg rng_state in
(key, (Some (), (map, eos))))
()
let () =
(*
IMap_get_and_update ->
(map_update) ->
(map_get) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMap_get_and_update
~stack_type:(int @$ option unit @$ map int unit @$ bot)
~kinstr:(IMap_get_and_update (dummy_loc, halt))
~intercept_stack:
(let map = Script_map.empty int in
(Script_int.zero, (None, (map, eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_map_and_key_in_map cfg rng_state in
(key, (Some (), (map, eos))))
()
let () =
(*
IMap_size ->
(map_update) ->
(map_get) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMap_size
~stack_type:(map int unit @$ bot)
~kinstr:(IMap_size (dummy_loc, halt))
~stack_sampler:(fun _cfg _rng_state ->
let map = Script_map.empty int in
fun () -> (map, eos))
()
end
module Big_maps = struct
let generate_big_map_and_key_in_map (cfg : Default_config.config) rng_state
=
let n =
Base_samplers.sample_in_interval rng_state ~range:cfg.sampler.set_size
in
let keys = adversarial_ints rng_state cfg n in
let map =
List.fold_left
(fun map i -> Script_map.update i (Some (Some ())) map)
(Script_map.empty int)
keys
in
let (module M) = Script_map.get_module map in
let key =
M.OPS.fold (fun k _ -> function None -> Some k | x -> x) M.boxed None
|> WithExceptions.Option.get ~loc:__LOC__
in
let big_map =
raise_if_error
(Lwt_main.run
( Execution_context.make ~rng_state >>=? fun (ctxt, _) ->
let big_map = Script_big_map.empty int unit_t in
Script_map.fold
(fun k v acc ->
acc >>=? fun (bm, ctxt_acc) ->
Script_big_map.update ctxt_acc k v bm)
map
(return (big_map, ctxt))
>|= Environment.wrap_tzresult
>>=? fun (big_map, _) -> return big_map ))
in
(key, big_map)
let () =
simple_benchmark
~name:Interpreter_workload.N_IEmpty_big_map
~stack_type:(unit @$ bot)
~kinstr:(IEmpty_big_map (dummy_loc, unit, unit, halt))
()
let () =
(*
IBig_map_mem ->
(update context with gas)
(big_map_mem) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IBig_map_mem
~stack_type:(int @$ big_map int unit @$ unit @$ bot)
~kinstr:(IBig_map_mem (dummy_loc, halt))
~intercept_stack:
(let map = Script_big_map.empty int unit in
(Script_int.zero, (map, ((), eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_big_map_and_key_in_map cfg rng_state in
(key, (map, ((), eos))))
()
let () =
(*
IBig_map_get ->
(big_map_get) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IBig_map_get
~stack_type:(int @$ big_map int unit @$ unit @$ bot)
~kinstr:(IBig_map_get (dummy_loc, halt))
~intercept_stack:
(let map = Script_big_map.empty int unit in
(Script_int.zero, (map, ((), eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_big_map_and_key_in_map cfg rng_state in
(key, (map, ((), eos))))
()
let () =
(*
IBig_map_update ->
(big_map_update) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IBig_map_update
~stack_type:(int @$ option unit @$ big_map int unit @$ bot)
~kinstr:(IBig_map_update (dummy_loc, halt))
~intercept_stack:
(let map = Script_big_map.empty int unit in
(Script_int.zero, (None, (map, eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_big_map_and_key_in_map cfg rng_state in
(key, (Some (), (map, eos))))
()
let () =
(*
IBig_map_get_and_update ->
(big_map_update) ->
(big_map_get) ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IBig_map_get_and_update
~stack_type:(int @$ option unit @$ big_map int unit @$ bot)
~kinstr:(IBig_map_get_and_update (dummy_loc, halt))
~intercept_stack:
(let map = Script_big_map.empty int unit in
(Script_int.zero, (None, (map, eos))))
~stack_sampler:(fun cfg rng_state () ->
let key, map = generate_big_map_and_key_in_map cfg rng_state in
(key, (Some (), (map, eos))))
()
end
module Strings = struct
open Script_string
let () =
simple_benchmark
~name:Interpreter_workload.N_IConcat_string
~intercept_stack:(Script_list.empty, eos)
~stack_type:(list string @$ bot)
~kinstr:(IConcat_string (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IConcat_string_pair
~intercept_stack:(empty, (empty, eos))
~stack_type:(string @$ string @$ bot)
~kinstr:(IConcat_string_pair (dummy_loc, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ISlice_string
~stack_type:(nat @$ nat @$ string @$ bot)
~kinstr:(ISlice_string (dummy_loc, halt))
~intercept_stack:
(let z = Script_int.zero_n in
(z, (z, (empty, eos))))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let string =
Samplers.Random_value.value Script_typed_ir.string_t rng_state
in
let len = nat_of_positive_int (length string) in
(* worst case: offset = 0 *)
(nat_of_positive_int 0, (len, (string, eos))))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IString_size
~stack_type:(string @$ bot)
~kinstr:(IString_size (dummy_loc, halt))
()
end
module Bytes = struct
(* Copy of [String] modulo renaming string to bytes. *)
let () =
simple_benchmark
~name:Interpreter_workload.N_IConcat_bytes
~intercept_stack:(Script_list.empty, eos)
~stack_type:(list bytes @$ bot)
~kinstr:(IConcat_bytes (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IConcat_bytes_pair
~intercept_stack:(Bytes.empty, (Bytes.empty, eos))
~stack_type:(bytes @$ bytes @$ bot)
~kinstr:(IConcat_bytes_pair (dummy_loc, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ISlice_bytes
~stack_type:(nat @$ nat @$ bytes @$ bot)
~kinstr:(ISlice_bytes (dummy_loc, halt))
~intercept_stack:
(let z = Script_int.zero_n in
(z, (z, (Bytes.empty, eos))))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let bytes =
Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
let len = nat_of_positive_int (Bytes.length bytes) in
(* worst case: offset = 0 *)
(nat_of_positive_int 0, (len, (bytes, eos))))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IBytes_size
~stack_type:(bytes @$ bot)
~kinstr:(IBytes_size (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAnd_bytes
~intercept_stack:(Bytes.empty, (Bytes.empty, eos))
~stack_type:(bytes @$ bytes @$ bot)
~kinstr:(IAnd_bytes (dummy_loc, halt))
()
let stack_sampler_for_or_and_xor_on_bytes cfg rng_state =
let _, (module Samplers) =
make_default_samplers cfg.Default_config.sampler
in
fun () ->
(* We benchmark the worst cases: when the two bytes have
the same length *)
let bytes1 =
Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
let bytes2 =
Bytes.init (Bytes.length bytes1) (fun _ ->
Char.chr (Random.State.int rng_state 256))
in
(bytes1, (bytes2, eos))
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IOr_bytes
~intercept_stack:(Bytes.empty, (Bytes.empty, eos))
~stack_type:(bytes @$ bytes @$ bot)
~kinstr:(IOr_bytes (dummy_loc, halt))
~stack_sampler:stack_sampler_for_or_and_xor_on_bytes
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IXor_bytes
~intercept_stack:(Bytes.empty, (Bytes.empty, eos))
~stack_type:(bytes @$ bytes @$ bot)
~kinstr:(IXor_bytes (dummy_loc, halt))
~stack_sampler:stack_sampler_for_or_and_xor_on_bytes
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INot_bytes
~intercept_stack:(Bytes.empty, eos)
~stack_type:(bytes @$ bot)
~kinstr:(INot_bytes (dummy_loc, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ILsl_bytes
~intercept_stack:(Bytes.empty, (Script_int.one_n, eos))
~stack_type:(bytes @$ nat @$ bot)
~kinstr:(ILsl_bytes (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let bytes =
Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
(* Avoid [n mod 8 = 0] which runs faster than the others. *)
let n =
(* 0-63999 without multiples of 8 *)
let n = Random.State.int rng_state 56000 in
(n / 7 * 8) + (n mod 7) + 1
in
let shift = Script_int.(abs (of_int n)) in
(bytes, (shift, eos)))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ILsr_bytes
~intercept_stack:(Bytes.empty, (Script_int.one_n, eos))
~stack_type:(bytes @$ nat @$ bot)
~kinstr:(ILsr_bytes (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let bytes =
Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
(* No need of samples of shift > bytes * 8 which are equivalent with
the case of shift = bytes * 8 where LSR returns empty bytes immediately *)
(* Avoid [n mod 8 = 0] which runs faster than the others. *)
let n =
let n =
Random.State.int rng_state ((Bytes.length bytes * 7) + 1)
in
(n / 7 * 8) + (n mod 7) + 1
in
let shift = Script_int.(abs (of_int n)) in
(bytes, (shift, eos)))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IBytes_nat
~stack_type:(nat @$ bot)
~kinstr:(IBytes_nat (dummy_loc, halt))
~intercept_stack:(Script_int.one_n, eos)
(* Avoid the optimized case of 0 *)
~stack_sampler:(fun cfg rng_state ->
let base_parameters =
{cfg.sampler.base_parameters with int_size = {min = 0; max = 4096}}
in
let sampler = {cfg.sampler with base_parameters} in
let _, (module Samplers) = make_default_samplers sampler in
fun () ->
let nat =
Samplers.Random_value.value Script_typed_ir.nat_t rng_state
in
(nat, eos))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_INat_bytes
~stack_type:(bytes @$ bot)
~kinstr:(INat_bytes (dummy_loc, halt))
~intercept_stack:(Bytes.empty, eos)
~stack_sampler:(fun cfg rng_state ->
let base_parameters =
{
cfg.sampler.base_parameters with
bytes_size = {min = 0; max = 4096};
}
in
let sampler = {cfg.sampler with base_parameters} in
let _, (module Samplers) = make_default_samplers sampler in
fun () ->
let bytes =
Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
(bytes, eos))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IBytes_int
~stack_type:(int @$ bot)
~kinstr:(IBytes_int (dummy_loc, halt))
~intercept_stack:(Script_int.one, eos)
(* Avoid the optimized case of 0 *)
~stack_sampler:(fun cfg rng_state ->
let base_parameters =
{cfg.sampler.base_parameters with int_size = {min = 0; max = 4096}}
in
let sampler = {cfg.sampler with base_parameters} in
let _, (module Samplers) = make_default_samplers sampler in
fun () ->
let int =
Samplers.Random_value.value Script_typed_ir.int_t rng_state
in
(int, eos))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IInt_bytes
~stack_type:(bytes @$ bot)
~kinstr:(IInt_bytes (dummy_loc, halt))
~intercept_stack:(Bytes.empty, eos)
~stack_sampler:(fun cfg rng_state ->
let base_parameters =
{
cfg.sampler.base_parameters with
bytes_size = {min = 0; max = 4096};
}
in
let sampler = {cfg.sampler with base_parameters} in
let _, (module Samplers) = make_default_samplers sampler in
fun () ->
let bytes =
Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
(bytes, eos))
()
end
module Timestamps = struct
let zero_timestamp = Script_timestamp.of_zint Z.zero
let zero_int = Script_int.zero
let () =
simple_benchmark
~name:Interpreter_workload.N_IAdd_seconds_to_timestamp
~intercept_stack:(zero_int, (zero_timestamp, eos))
~stack_type:(int @$ timestamp @$ bot)
~kinstr:(IAdd_seconds_to_timestamp (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAdd_timestamp_to_seconds
~intercept_stack:(zero_timestamp, (zero_int, eos))
~stack_type:(timestamp @$ int @$ bot)
~kinstr:(IAdd_timestamp_to_seconds (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISub_timestamp_seconds
~intercept_stack:(zero_timestamp, (zero_int, eos))
~stack_type:(timestamp @$ int @$ bot)
~kinstr:(ISub_timestamp_seconds (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IDiff_timestamps
~intercept_stack:(zero_timestamp, (zero_timestamp, eos))
~stack_type:(timestamp @$ timestamp @$ bot)
~kinstr:(IDiff_timestamps (dummy_loc, halt))
()
end
module Tez = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_IAdd_tez
~stack_type:(mutez @$ mutez @$ bot)
~kinstr:(IAdd_tez (dummy_loc, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ISub_tez
~stack_type:(mutez @$ mutez @$ bot)
~kinstr:(ISub_tez (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) =
make_default_samplers cfg.Default_config.sampler
in
fun () ->
let a = Samplers.Random_value.value mutez rng_state in
let b =
match Alpha_context.Tez.(a /? 2L) with
| Error _ -> assert false
| Ok x -> x
in
(a, (b, eos)))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ISub_tez_legacy
~stack_type:(mutez @$ mutez @$ bot)
~kinstr:(ISub_tez_legacy (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) =
make_default_samplers cfg.Default_config.sampler
in
fun () ->
let a = Samplers.Random_value.value mutez rng_state in
let b =
match Alpha_context.Tez.(a /? 2L) with
| Error _ -> assert false
| Ok x -> x
in
(a, (b, eos)))
()
let sample_tez_nat (module Samplers : Michelson_samplers.S) rng_state =
let mutez = Samplers.Random_value.value mutez rng_state in
let mutez_int64 = Alpha_context.Tez.to_mutez mutez in
let int64 = Int64.(div max_int (mul mutez_int64 2L)) in
let nat =
match Script_int.(is_nat (of_int64 int64)) with
| None -> assert false
| Some nat -> nat
in
(mutez, nat)
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMul_teznat
~stack_type:(mutez @$ nat @$ bot)
~kinstr:(IMul_teznat (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, samplers = make_default_samplers cfg.sampler in
fun () ->
let mutez, nat = sample_tez_nat samplers rng_state in
(mutez, (nat, eos)))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IMul_nattez
~stack_type:(nat @$ mutez @$ bot)
~kinstr:(IMul_nattez (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, samplers = make_default_samplers cfg.sampler in
fun () ->
let mutez, nat = sample_tez_nat samplers rng_state in
(nat, (mutez, eos)))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IEdiv_teznat
~stack_type:(mutez @$ nat @$ bot)
~kinstr:(IEdiv_teznat (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, samplers = make_default_samplers cfg.sampler in
fun () ->
let mutez, nat = sample_tez_nat samplers rng_state in
(mutez, (nat, eos)))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IEdiv_tez
~stack_type:(mutez @$ mutez @$ bot)
~kinstr:(IEdiv_tez (dummy_loc, halt))
()
end
module Booleans = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_IOr
~stack_type:(bool @$ bool @$ bot)
~kinstr:(IOr (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAnd
~stack_type:(bool @$ bool @$ bot)
~kinstr:(IAnd (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IXor
~stack_type:(bool @$ bool @$ bot)
~kinstr:(IXor (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INot
~stack_type:(bool @$ bot)
~kinstr:(INot (dummy_loc, halt))
()
end
module Integers = struct
let zero = Script_int.zero
let zero_n = Script_int.zero_n
let () =
simple_benchmark
~name:Interpreter_workload.N_IIs_nat
~stack_type:(int @$ bot)
~kinstr:(IIs_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INeg
~intercept_stack:(zero, eos)
~stack_type:(int @$ bot)
~kinstr:(INeg (dummy_loc, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IAbs_int
~stack_type:(int @$ bot)
~kinstr:(IAbs_int (dummy_loc, halt))
~intercept_stack:(zero, eos)
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let x = Samplers.Michelson_base.nat rng_state in
let neg_x = Script_int.neg x in
(neg_x, eos))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IInt_nat
~stack_type:(nat @$ bot)
~kinstr:(IInt_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAdd_int
~intercept_stack:(zero, (zero, eos))
~stack_type:(int @$ int @$ bot)
~kinstr:(IAdd_int (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAdd_nat
~intercept_stack:(zero_n, (zero_n, eos))
~stack_type:(nat @$ nat @$ bot)
~kinstr:(IAdd_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISub_int
~intercept_stack:(zero, (zero, eos))
~stack_type:(int @$ int @$ bot)
~kinstr:(ISub_int (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IMul_int
~intercept_stack:(zero, (zero, eos))
~stack_type:(int @$ int @$ bot)
~kinstr:(IMul_int (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IMul_nat
~intercept_stack:(zero_n, (zero, eos))
~stack_type:(nat @$ int @$ bot)
~kinstr:(IMul_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IEdiv_int
~intercept_stack:(zero, (zero, eos))
~stack_type:(int @$ int @$ bot)
~kinstr:(IEdiv_int (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IEdiv_nat
~intercept_stack:(zero_n, (zero, eos))
~stack_type:(nat @$ int @$ bot)
~kinstr:(IEdiv_nat (dummy_loc, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ILsl_nat
~intercept_stack:(zero_n, (zero_n, eos))
~stack_type:(nat @$ nat @$ bot)
~kinstr:(ILsl_nat (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let x = Samplers.Michelson_base.nat rng_state in
(* shift must be in [0;256]: 1 byte max *)
let shift =
Script_int.(abs (of_int (Random.State.int rng_state 256)))
in
(x, (shift, eos)))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ILsr_nat
~intercept_stack:(zero_n, (zero_n, eos))
~stack_type:(nat @$ nat @$ bot)
~kinstr:(ILsr_nat (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let x = Samplers.Michelson_base.nat rng_state in
(* shift must be in [0;256]: 1 byte max *)
let shift =
Script_int.(abs (of_int (Random.State.int rng_state 256)))
in
(x, (shift, eos)))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IOr_nat
~intercept_stack:(zero_n, (zero_n, eos))
~stack_type:(nat @$ nat @$ bot)
~kinstr:(IOr_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAnd_nat
~intercept_stack:(zero_n, (zero_n, eos))
~stack_type:(nat @$ nat @$ bot)
~kinstr:(IAnd_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAnd_int_nat
~intercept_stack:(zero, (zero_n, eos))
~stack_type:(int @$ nat @$ bot)
~kinstr:(IAnd_int_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IXor_nat
~intercept_stack:(zero_n, (zero_n, eos))
~stack_type:(nat @$ nat @$ bot)
~kinstr:(IXor_nat (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INot_int
~intercept_stack:(zero, eos)
~stack_type:(int @$ bot)
~kinstr:(INot_int (dummy_loc, halt))
()
end
module Control = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_IIf
~stack_type:(bool @$ unit @$ bot)
~kinstr:
(IIf
{
loc = dummy_loc;
branch_if_true = halt;
branch_if_false = halt;
k = halt;
})
()
let () =
(*
ILoop ->
either
- IHalt (false on top of stack)
- IPush false ; IHalt (true on top of stack)
*)
let push_false = IPush (dummy_loc, bool, false, halt) in
simple_benchmark
~name:Interpreter_workload.N_ILoop
~stack_type:(bool @$ bot)
~kinstr:(ILoop (dummy_loc, push_false, halt))
()
let () =
(*
ILoop_left ->
ICons_right ->
IHalt
*)
let cons_r = ICons_right (dummy_loc, unit, halt) in
simple_benchmark
~name:Interpreter_workload.N_ILoop_left
~stack_type:(cor unit unit @$ bot)
~kinstr:(ILoop_left (dummy_loc, cons_r, halt))
()
let () =
(*
IDip ->
IHalt ->
IPush ->
IHalt
*)
simple_benchmark
~name:Interpreter_workload.N_IDip
~stack_type:(unit @$ unit @$ bot)
~kinstr:(IDip (dummy_loc, halt, Some unit, halt))
()
let dummy_lambda =
let open Script_typed_ir in
let descr =
{
kloc = dummy_loc;
kbef = unit @$ bot;
kaft = unit @$ bot;
kinstr = halt;
}
in
Lam (descr, Micheline.Int (dummy_loc, Z.zero))
let dummy_lambda_rec =
let open Script_typed_ir in
let descr =
{
kloc = dummy_loc;
kbef = unit @$ lambda unit unit @$ bot;
kaft = unit @$ bot;
kinstr =
IDrop
(dummy_loc, IDrop (dummy_loc, IPush (dummy_loc, unit, (), halt)));
}
in
LamRec (descr, Micheline.Int (dummy_loc, Z.zero))
let () =
(*
IExec ->
(switch to in-context gas-counting) ->
interp lambda code ->
IHalt
*)
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IExec
~stack_type:(unit @$ lambda unit unit @$ bot)
~kinstr:(IExec (dummy_loc, Some (unit @$ bot), halt))
~stack_sampler:(fun _cfg rng_state () ->
if Base_samplers.uniform_bool rng_state then ((), (dummy_lambda, eos))
else ((), (dummy_lambda_rec, eos)))
()
let () =
(*
IApply ->
unparse unit ->
unparse unit_ty ->
construct term ->
IHalt
*)
let dummy_lambda_pair =
let open Script_typed_ir in
let descr =
{
kloc = dummy_loc;
kbef = cpair unit unit @$ bot;
kaft = unit @$ bot;
kinstr = ICdr (dummy_loc, halt);
}
in
Lam (descr, Micheline.Int (dummy_loc, Z.zero))
in
let dummy_lambda_pair_rec =
let open Script_typed_ir in
let descr =
{
kloc = dummy_loc;
kbef = cpair unit unit @$ lambda (cpair unit unit) unit @$ bot;
kaft = unit @$ bot;
kinstr =
IDrop
(dummy_loc, IDrop (dummy_loc, IPush (dummy_loc, unit, (), halt)));
}
in
LamRec (descr, Micheline.Int (dummy_loc, Z.zero))
in
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_IApply
~stack_type:(unit @$ lambda (cpair unit unit) unit @$ bot)
~kinstr:(IApply (dummy_loc, unit, halt))
~stack_sampler:(fun _cfg rng_state () ->
if Base_samplers.uniform_bool rng_state then
((), (dummy_lambda_pair, eos))
else ((), (dummy_lambda_pair_rec, eos)))
()
let () =
(*
ILambda ->
IHalt
*)
simple_benchmark
~name:Interpreter_workload.N_ILambda
~stack_type:(unit @$ bot)
~kinstr:(ILambda (dummy_loc, dummy_lambda, halt))
()
let () =
(*
ILambda (rec) ->
IHalt
*)
simple_benchmark
~name:Interpreter_workload.N_ILambda
~salt:"_rec"
~stack_type:(unit @$ bot)
~kinstr:(ILambda (dummy_loc, dummy_lambda_rec, halt))
()
let () =
(*
IFailwith ->
(unparse_data Unit) ->
(strip_locations) ->
fail
*)
simple_benchmark
~name:Interpreter_workload.N_IFailwith
~amplification:100
~stack_type:(unit @$ bot)
~kinstr:(IFailwith (dummy_loc, unit))
()
end
module Comparison = struct
let () =
benchmark
~name:Interpreter_workload.N_ICompare
~kinstr_and_stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let size =
Base_samplers.sample_in_interval
rng_state
~range:cfg.compare.type_size
in
let (Script_ir_translator.Ex_comparable_ty ty) =
Samplers.Random_type.m_comparable_type ~size rng_state
in
let value = Samplers.Random_value.comparable ty rng_state in
let kinstr = ICompare (dummy_loc, ty, halt) in
Ex_stack_and_kinstr
{
stack = (value, (value, eos));
stack_type = ty @$ ty @$ bot;
kinstr;
})
()
end
module Comparators = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_IEq
~stack_type:(int @$ bot)
~kinstr:(IEq (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INeq
~stack_type:(int @$ bot)
~kinstr:(INeq (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ILt
~stack_type:(int @$ bot)
~kinstr:(ILt (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IGt
~stack_type:(int @$ bot)
~kinstr:(IGt (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ILe
~stack_type:(int @$ bot)
~kinstr:(ILe (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IGe
~stack_type:(int @$ bot)
~kinstr:(IGe (dummy_loc, halt))
()
end
module Proto = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_IAddress
~stack_type:(contract unit @$ bot)
~kinstr:(IAddress (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IContract
~stack_type:(address @$ bot)
~kinstr:
(IContract (dummy_loc, unit, Alpha_context.Entrypoint.default, halt))
()
let () =
simple_benchmark_with_stack_sampler
~name:Interpreter_workload.N_ITransfer_tokens
~stack_type:(unit @$ mutez @$ contract unit @$ bot)
~kinstr:(ITransfer_tokens (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
fun () ->
let contract =
Samplers.Random_value.value (contract unit) rng_state
in
let amount =
match contract with
| Typed_implicit _ | Typed_originated _ ->
Samplers.Random_value.value mutez rng_state
| Typed_sc_rollup _ -> Alpha_context.Tez.zero
in
((), (amount, (contract, eos))))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IImplicit_account
~stack_type:(key_hash @$ bot)
~kinstr:(IImplicit_account (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ICreate_contract
~stack_type:(option key_hash @$ mutez @$ unit @$ bot)
~kinstr:
(ICreate_contract
{
loc = dummy_loc;
storage_type = unit;
code = Micheline.(strip_locations @@ Seq (0, []));
k = halt;
})
()
let () =
let name =
match Protocol.Script_string.of_string "view" with
| Ok s -> s
| Error _ -> assert false
in
simple_benchmark
~name:Interpreter_workload.N_IView
~stack_type:(unit @$ address @$ bot)
~kinstr:
(IView
( dummy_loc,
View_signature {name; input_ty = unit; output_ty = unit},
Some bot,
halt ))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISet_delegate
~stack_type:(option key_hash @$ bot)
~kinstr:(ISet_delegate (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_INow
~stack_type:(unit @$ bot)
~kinstr:(INow (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IMin_block_time
~stack_type:bot
~kinstr:(IMin_block_time (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IBalance
~stack_type:(unit @$ bot)
~kinstr:(IBalance (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ILevel
~stack_type:(unit @$ bot)
~kinstr:(ILevel (dummy_loc, halt))
()
let check_signature (algo : Signature.algo) ~for_intercept =
let name =
match algo with
| Signature.Ed25519 -> Interpreter_workload.N_ICheck_signature_ed25519
| Signature.Secp256k1 ->
Interpreter_workload.N_ICheck_signature_secp256k1
| Signature.P256 -> Interpreter_workload.N_ICheck_signature_p256
| Signature.Bls -> Interpreter_workload.N_ICheck_signature_bls
in
benchmark_with_stack_sampler
~intercept:for_intercept
~name
~stack_type:(public_key @$ signature @$ bytes @$ bot)
~kinstr:(ICheck_signature (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let (module Crypto_samplers), (module Samplers) =
make_default_samplers ~algo:(`Algo algo) cfg.Default_config.sampler
in
fun () ->
let _pkh, pk, sk = Crypto_samplers.all rng_state in
let unsigned_message =
if for_intercept then Environment.Bytes.empty
else Samplers.Random_value.value Script_typed_ir.bytes_t rng_state
in
let signed_message = Signature.sign sk unsigned_message in
let signed_message = Script_signature.make signed_message in
(pk, (signed_message, (unsigned_message, eos))))
()
let check_signature algo =
check_signature algo ~for_intercept:true ;
check_signature algo ~for_intercept:false
let () = check_signature Signature.Ed25519
let () = check_signature Signature.Secp256k1
let () = check_signature Signature.P256
let () = check_signature Signature.Bls
let () =
simple_benchmark
~name:Interpreter_workload.N_IHash_key
~stack_type:(public_key @$ bot)
~kinstr:(IHash_key (dummy_loc, halt))
()
let () =
benchmark
~name:Interpreter_workload.N_IPack
~kinstr_and_stack_sampler:(fun _cfg _rng_state ->
let kinstr = IPack (dummy_loc, unit, halt) in
fun () ->
Ex_stack_and_kinstr
{stack = ((), eos); stack_type = unit @$ bot; kinstr})
()
let () =
benchmark
~name:Interpreter_workload.N_IUnpack
~kinstr_and_stack_sampler:(fun _cfg rng_state ->
let b =
raise_if_error
(Lwt_main.run
( Execution_context.make ~rng_state >>=? fun (ctxt, _) ->
Script_ir_translator.pack_data ctxt unit ()
>|= Environment.wrap_tzresult
>>=? fun (bytes, _) -> return bytes ))
in
let kinstr = IUnpack (dummy_loc, unit, halt) in
fun () ->
Ex_stack_and_kinstr
{stack = (b, eos); stack_type = bytes @$ bot; kinstr})
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IBlake2b
~intercept_stack:(Environment.Bytes.empty, eos)
~stack_type:(bytes @$ bot)
~kinstr:(IBlake2b (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISha256
~intercept_stack:(Environment.Bytes.empty, eos)
~stack_type:(bytes @$ bot)
~kinstr:(ISha256 (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISha512
~intercept_stack:(Environment.Bytes.empty, eos)
~stack_type:(bytes @$ bot)
~kinstr:(ISha512 (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IKeccak
~intercept_stack:(Environment.Bytes.empty, eos)
~stack_type:(bytes @$ bot)
~kinstr:(IKeccak (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISha3
~intercept_stack:(Environment.Bytes.empty, eos)
~stack_type:(bytes @$ bot)
~kinstr:(ISha3 (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISource
~stack_type:(unit @$ bot)
~kinstr:(ISource (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISender
~stack_type:(unit @$ bot)
~kinstr:(ISender (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISelf
~stack_type:(unit @$ bot)
~kinstr:
(ISelf (dummy_loc, unit, Alpha_context.Entrypoint.default, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ISelf_address
~stack_type:(unit @$ bot)
~kinstr:(ISelf_address (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IAmount
~stack_type:(unit @$ bot)
~kinstr:(IAmount (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IChainId
~stack_type:(unit @$ bot)
~kinstr:(IChainId (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IVoting_power
~stack_type:(key_hash @$ bot)
~kinstr:(IVoting_power (dummy_loc, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_ITotal_voting_power
~stack_type:(unit @$ bot)
~kinstr:(ITotal_voting_power (dummy_loc, halt))
()
end
let () =
let memo_size =
match Alpha_context.Sapling.Memo_size.parse_z Z.zero with
| Error _ -> assert false
| Ok sz -> sz
in
simple_benchmark
~name:Interpreter_workload.N_ISapling_empty_state
~stack_type:(unit @$ bot)
~kinstr:(ISapling_empty_state (dummy_loc, memo_size, halt))
()
module type Type_transaction = sig
val type_transaction : Sapling_generation.type_transaction
val suffix : string
end
module Register_Sapling_benchmark (Type_transaction : Type_transaction) =
struct
let is_empty =
match Type_transaction.type_transaction with Empty -> true | _ -> false
let () =
(* Note that memo_size is hardcoded to 0 in module [Sapling_generation]. *)
let memo_size =
match Alpha_context.Sapling.Memo_size.parse_z Z.zero with
| Error _ -> assert false
| Ok sz -> sz
in
let info, name =
info_and_name
~intercept:is_empty
("ISapling_verify_update_" ^ Type_transaction.suffix)
in
let module B : Benchmark.S = struct
let name = name
let info = info
let module_filename = __FILE__
let generated_code_destination = None
include Default_config
include Default_boilerplate
let models =
Interpreter_model.make_model
(Instr_name Interpreter_workload.N_ISapling_verify_update)
let stack_type =
let spl_state = sapling_state memo_size in
let spl_tx = sapling_transaction memo_size in
spl_tx @$ spl_state @$ bot
let kinstr = ISapling_verify_update (dummy_loc, halt)
let prepare_sapling_execution_environment sapling_forge_rng_seed
sapling_transition =
let sapling_forge_rng_state =
Random.State.make
@@ Option.fold
~none:Sapling_generation.shared_seed
~some:(fun seed -> [|seed|])
sapling_forge_rng_seed
in
(* Prepare context. We _must_ reuse the same seed as the one used for
the context when generating the transactions. This ensures that the
bootstrap account match and that the transactions can be replayed. *)
let result =
Lwt_main.run
( Execution_context.make ~rng_state:sapling_forge_rng_state
>>=? fun (ctxt, step_constants) ->
(* Prepare a sapling state able to replay the transition. *)
Sapling_generation.prepare_seeded_state sapling_transition ctxt
>>=? fun (_, _, _, _, ctxt, state_id) ->
Alpha_context.Sapling.(state_from_id ctxt (Id.parse_z state_id))
>|= Environment.wrap_tzresult
>>=? fun (state, ctxt) -> return (ctxt, state, step_constants)
)
in
match result with
| Ok r -> r
| Error _ ->
Format.eprintf
"Error in prepare_sapling_execution_environment, aborting@." ;
Stdlib.failwith "prepare_sapling_execution_environment"
let create_benchmarks ~rng_state ~bench_num (config : config) =
ignore rng_state ;
match config.sapling with
| {sapling_txs_file; seed} ->
let transitions =
Sapling_generation.load
~filename:sapling_txs_file
Type_transaction.type_transaction
in
let length = List.length transitions in
if length < bench_num && not is_empty then
Format.eprintf
"ISapling_verify_update: warning, only %d available \
transactions (requested %d)@."
length
bench_num ;
let transitions =
List.take_n (min bench_num length) transitions
in
List.map
(fun (_, transition) () ->
let ctxt, state, step_constants =
prepare_sapling_execution_environment seed transition
in
let address =
Alpha_context.Contract.(
to_b58check (Originated step_constants.self))
in
let chain_id =
Environment.Chain_id.to_b58check step_constants.chain_id
in
let anti_replay = address ^ chain_id in
(* Checks that the transaction is correct*)
let () =
match
Sapling_validator.verify_update
(Sapling_generation.alpha_to_raw ctxt)
(Obj.magic state)
transition.sapling_tx
anti_replay
|> Lwt_main.run
with
| Ok (_, Some _) -> ()
| Ok (_, None) ->
Stdlib.failwith "benchmarked transaction is incorrect"
| _ -> assert false
in
let stack_instr =
Ex_stack_and_kinstr
{
stack = (transition.sapling_tx, (state, eos));
stack_type;
kinstr;
}
in
benchmark_from_kinstr_and_stack
ctxt
step_constants
stack_instr)
transitions
end in
Registration_helpers.register (module B)
end
module Sapling_empty = struct
let module A = Register_Sapling_benchmark (struct
let type_transaction = Sapling_generation.Empty
let suffix = "empty"
end) in
()
end
module Sapling_no_inputs = struct
let module A = Register_Sapling_benchmark (struct
let type_transaction = Sapling_generation.No_inputs
let suffix = "no_inputs"
end) in
()
end
module Sapling_no_outputs = struct
let module A = Register_Sapling_benchmark (struct
let type_transaction = Sapling_generation.No_outputs
let suffix = "no_output"
end) in
()
end
module Sapling_full = struct
let module A = Register_Sapling_benchmark (struct
let type_transaction = Sapling_generation.Full_transaction
let suffix = "full"
end) in
()
end
(* when benchmarking, compile bls12-381-unix without ADX, see
https://gitlab.com/dannywillems/ocaml-bls12-381/-/blob/71d0b4d467fbfaa6452d702fcc408d7a70916a80/README.md#install
*)
module Bls12_381 = struct
let check () =
if not Bls12_381.built_with_blst_portable then (
Format.eprintf
"BLS must be built without ADX to run the BLS benchmarks. Try \
compiling again after setting the environment variable \
BLST_PORTABLE. Aborting.@." ;
Stdlib.failwith "bls_not_built_with_blst_portable")
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IAdd_bls12_381_g1
~stack_type:(bls12_381_g1 @$ bls12_381_g1 @$ bot)
~kinstr:(IAdd_bls12_381_g1 (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IAdd_bls12_381_g2
~stack_type:(bls12_381_g2 @$ bls12_381_g2 @$ bot)
~kinstr:(IAdd_bls12_381_g2 (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IAdd_bls12_381_fr
~stack_type:(bls12_381_fr @$ bls12_381_fr @$ bot)
~kinstr:(IAdd_bls12_381_fr (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IMul_bls12_381_g1
~stack_type:(bls12_381_g1 @$ bls12_381_fr @$ bot)
~kinstr:(IMul_bls12_381_g1 (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IMul_bls12_381_g2
~stack_type:(bls12_381_g2 @$ bls12_381_fr @$ bot)
~kinstr:(IMul_bls12_381_g2 (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IMul_bls12_381_fr
~stack_type:(bls12_381_fr @$ bls12_381_fr @$ bot)
~kinstr:(IMul_bls12_381_fr (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IMul_bls12_381_z_fr
~stack_type:(bls12_381_fr @$ int @$ bot)
~kinstr:(IMul_bls12_381_z_fr (dummy_loc, halt))
()
let () =
benchmark_with_stack_sampler
~check
~name:Interpreter_workload.N_IMul_bls12_381_z_fr
~intercept:true
~stack_type:(bls12_381_fr @$ int @$ bot)
~kinstr:(IMul_bls12_381_z_fr (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
let fr_sampler = Samplers.Random_value.value bls12_381_fr in
let zero = Script_int.zero in
fun () -> (fr_sampler rng_state, (zero, eos)))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IMul_bls12_381_fr_z
~stack_type:(int @$ bls12_381_fr @$ bot)
~kinstr:(IMul_bls12_381_fr_z (dummy_loc, halt))
()
let () =
benchmark_with_stack_sampler
~check
~name:Interpreter_workload.N_IMul_bls12_381_fr_z
~intercept:true
~stack_type:(int @$ bls12_381_fr @$ bot)
~kinstr:(IMul_bls12_381_fr_z (dummy_loc, halt))
~stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
let fr_sampler = Samplers.Random_value.value bls12_381_fr in
let zero = Script_int.zero in
fun () -> (zero, (fr_sampler rng_state, eos)))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_IInt_bls12_381_z_fr
~stack_type:(bls12_381_fr @$ bot)
~kinstr:(IInt_bls12_381_fr (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_INeg_bls12_381_g1
~stack_type:(bls12_381_g1 @$ bot)
~kinstr:(INeg_bls12_381_g1 (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_INeg_bls12_381_g2
~stack_type:(bls12_381_g2 @$ bot)
~kinstr:(INeg_bls12_381_g2 (dummy_loc, halt))
()
let () =
simple_benchmark
~check
~name:Interpreter_workload.N_INeg_bls12_381_fr
~stack_type:(bls12_381_fr @$ bot)
~kinstr:(INeg_bls12_381_fr (dummy_loc, halt))
()
let () =
let (Ty_ex_c p) = pair bls12_381_g1 bls12_381_g2 in
simple_benchmark
~check
~name:Interpreter_workload.N_IPairing_check_bls12_381
~stack_type:(list p @$ bot)
~kinstr:(IPairing_check_bls12_381 (dummy_loc, halt))
()
end
module Tickets = struct
let () =
simple_benchmark
~name:Interpreter_workload.N_ITicket
~stack_type:(unit @$ nat @$ bot)
~kinstr:(ITicket (dummy_loc, Some unit, halt))
()
let () =
simple_benchmark
~name:Interpreter_workload.N_IRead_ticket
~stack_type:(ticket unit @$ bot)
~kinstr:(IRead_ticket (dummy_loc, Some unit, halt))
()
let split_ticket_instr = ISplit_ticket (dummy_loc, halt)
let stack_type = ticket unit @$ cpair nat nat @$ bot
let () =
let one = Script_int.one_n in
let ticket =
{
ticketer =
Alpha_context.Contract.Implicit
Environment.Signature.Public_key_hash.zero;
contents = ();
amount = Ticket_amount.(add one one);
}
in
benchmark_with_fixed_stack
~intercept:true
~name:Interpreter_workload.N_ISplit_ticket
~stack_type
~stack:(ticket, ((one, one), eos))
~kinstr:split_ticket_instr
()
let () =
benchmark
~name:Interpreter_workload.N_ISplit_ticket
~kinstr_and_stack_sampler:(fun config rng_state ->
let _, (module Samplers) =
make_default_samplers config.Default_config.sampler
in
fun () ->
let x_amount =
Script_int.succ_n @@ Samplers.Random_value.value nat rng_state
in
let y_amount =
Script_int.succ_n @@ Samplers.Random_value.value nat rng_state
in
let amount = Script_int.add_n x_amount y_amount in
let amount =
(* this is safe because x_amount > 0 and y_amount > 0 *)
WithExceptions.Option.get ~loc:__LOC__
@@ Ticket_amount.of_n amount
in
let ticket = Samplers.Random_value.value (ticket unit) rng_state in
let ticket = {ticket with amount} in
Ex_stack_and_kinstr
{
stack = (ticket, ((x_amount, y_amount), eos));
stack_type;
kinstr = split_ticket_instr;
})
()
let join_tickets_instr = IJoin_tickets (dummy_loc, string, halt)
let ticket_str = ticket string
let stack_type =
let (Ty_ex_c p) = pair ticket_str ticket_str in
p @$ bot
let () =
benchmark
~intercept:true
~name:Interpreter_workload.N_IJoin_tickets
~kinstr_and_stack_sampler:(fun config rng_state ->
let _, (module Samplers) =
make_default_samplers config.Default_config.sampler
in
fun () ->
let ticket =
Samplers.Random_value.value (ticket string) rng_state
in
let ticket =
{
ticket with
contents = Script_string.empty;
amount = Ticket_amount.one;
}
in
Ex_stack_and_kinstr
{
stack = ((ticket, ticket), eos);
stack_type;
kinstr = join_tickets_instr;
})
()
let () =
benchmark
~name:Interpreter_workload.N_IJoin_tickets
~kinstr_and_stack_sampler:(fun config rng_state ->
let _, (module Samplers) =
make_default_samplers config.Default_config.sampler
in
fun () ->
let ticket =
Samplers.Random_value.value (ticket string) rng_state
in
let alt_amount =
let amount = Samplers.Random_value.value nat rng_state in
let open Ticket_amount in
match of_n amount with
| Some amount -> add amount one
| None -> one
in
let ticket' = {ticket with amount = alt_amount} in
Ex_stack_and_kinstr
{
stack = ((ticket, ticket'), eos);
stack_type;
kinstr = join_tickets_instr;
})
()
end
module Timelock = struct
let name = Interpreter_workload.N_IOpen_chest
let stack_type =
Michelson_types.chest_key @$ Michelson_types.chest @$ nat @$ bot
let kinstr = IOpen_chest (dummy_loc, halt)
let resulting_stack chest chest_key time =
let chest = Script_timelock.make_chest chest in
let chest_key = Script_timelock.make_chest_key chest_key in
( chest_key,
( chest,
( Script_int.is_nat (Script_int.of_int time)
|> WithExceptions.Option.get ~loc:"Timelock:gas benchmarks",
eos ) ) )
let () =
benchmark_with_stack_sampler
~intercept:true
~name
~kinstr
~stack_type
~stack_sampler:(fun _ rng_state () ->
let chest, chest_key =
Timelock_samplers.chest_sampler ~plaintext_size:1 ~time:0 ~rng_state
in
resulting_stack chest chest_key 0)
()
let () =
benchmark_with_stack_sampler
~name
~kinstr
~stack_type
~stack_sampler:(fun _ rng_state () ->
let log_time =
Base_samplers.sample_in_interval
~range:{min = 0; max = 29}
rng_state
in
let time = Random.State.int rng_state (Int.shift_left 1 log_time) in
let plaintext_size =
Base_samplers.sample_in_interval
~range:{min = 1; max = 10000}
rng_state
in
let chest, chest_key =
Timelock_samplers.chest_sampler ~plaintext_size ~time ~rng_state
in
resulting_stack chest chest_key time)
()
end
module Continuations = struct
let () =
(*
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KNil
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KNil in
let stack = eos in
let stack_type = bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KCons -> step
KHalt -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KCons
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KCons (halt, KNil) in
let stack = ((), eos) in
let stack_type = unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KReturn -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KReturn
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KReturn (eos, Some (unit @$ bot), KNil) in
let stack = ((), eos) in
let stack_type = unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KView_exit -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KView_exit
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let open Script_typed_ir in
let open Alpha_context in
let step_constants =
{
sender = Contract (Implicit Signature.Public_key_hash.zero);
payer = Signature.Public_key_hash.zero;
self = Contract_hash.zero;
amount = Tez.zero;
balance = Tez.zero;
chain_id = Chain_id.zero;
now = Script_timestamp.of_zint Z.zero;
level = Script_int.zero_n;
}
in
let cont = KView_exit (step_constants, KNil) in
let stack = ((), eos) in
let stack_type = unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KLoop_in -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KLoop_in
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KLoop_in (IPush (dummy_loc, bool, false, halt), KNil) in
let stack = (false, ((), eos)) in
let stack_type = bool @$ unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KLoop_in_left -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KLoop_in_left
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont =
KLoop_in_left (ICons_right (dummy_loc, unit, halt), KNil)
in
let stack = (R (), eos) in
let stack_type = cor unit unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KUndip -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KUndip
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KUndip ((), Some unit, KNil) in
let stack = eos in
let stack_type = bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KIter (empty case) -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KIter
~salt:"_empty"
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KIter (IDrop (dummy_loc, halt), Some unit, [], KNil) in
let stack = ((), eos) in
let stack_type = unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KIter (nonempty case) -> step
KDrop -> step
KHalt -> next
KIter (empty case) -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KIter
~salt:"_nonempty"
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let cont = KIter (IDrop (dummy_loc, halt), Some unit, [()], KNil) in
let stack = ((), eos) in
let stack_type = unit @$ bot in
fun () -> Ex_stack_and_cont {stack; cont; stack_type})
()
let () =
(*
KList_enter_body ([()], bot accumulator case) -> step
KHalt -> next
KList_exit_body ([], []) ->
KList_enter_body ([], [()] ->
List.rev singleton
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KList_enter_body
~salt:"_singleton_list"
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let kbody = halt in
fun () ->
let cont =
KList_enter_body
(kbody, [()], Script_list.empty, Some (list unit), 1, KNil)
in
Ex_stack_and_cont
{stack = ((), eos); stack_type = unit @$ bot; cont})
()
let () =
(*
KList_enter_body (empty list, nonempty accumulator case) ->
{List.rev n elements} -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KList_enter_body
~salt:"_terminal"
~cont_and_stack_sampler:(fun cfg rng_state ->
let _, (module Samplers) = make_default_samplers cfg.sampler in
let kbody = halt in
fun () ->
let ys = Samplers.Random_value.value (list unit) rng_state in
let cont =
KList_enter_body (kbody, [], ys, Some (list unit), ys.length, KNil)
in
Ex_stack_and_cont
{stack = ((), eos); stack_type = unit @$ bot; cont})
()
let () =
(*
KList_enter_body (empty list, bot accumulator case) ->
{List.rev singleton} -> next
KNil
*)
continuation_benchmark
~amplification:100
~intercept:true
~name:Interpreter_workload.N_KList_enter_body
~salt:"_terminal"
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let kbody = halt in
fun () ->
let cont =
KList_enter_body
(kbody, [], Script_list.empty, Some (list unit), 1, KNil)
in
Ex_stack_and_cont
{stack = ((), eos); stack_type = unit @$ bot; cont})
()
let () =
(*
KList_exit_body (empty list) -> next
KList_enter_body ->
{List.rev 1 element} -> next
KNil
*)
continuation_benchmark
~amplification:100
~intercept:true
~name:Interpreter_workload.N_KList_exit_body
~salt:"_terminal"
~cont_and_stack_sampler:(fun _cfg _rng_state ->
let kbody = halt in
let cont =
KList_exit_body
(kbody, [], Script_list.empty, Some (list unit), 1, KNil)
in
fun () ->
Ex_stack_and_cont
{stack = ((), ((), eos)); stack_type = unit @$ unit @$ bot; cont})
()
let stack_type = cpair int unit @$ unit @$ bot
let map_enter_body_code =
let kbody = ICdr (dummy_loc, halt) in
fun accu ->
KMap_enter_body
(kbody, accu, Script_map.empty int, Some (map int unit), KNil)
let () =
(*
KMap_enter_body (empty case) -> next
KNil
*)
continuation_benchmark
~amplification:100
~salt:"_empty"
~name:Interpreter_workload.N_KMap_enter_body
~cont_and_stack_sampler:(fun _cfg _rng_state () ->
Ex_stack_and_cont
{
stack = ((), eos);
stack_type = unit @$ bot;
cont = map_enter_body_code [];
})
()
let () =
(*
KMap_enter_body (singleton case) -> step
KCdr -> step
KHalt -> next
KMap_exit_body -> next
(map_update)
KMap_enter_body (empty case) -> next
KNil
*)
continuation_benchmark
~amplification:100
~salt:"_singleton"
~name:Interpreter_workload.N_KMap_enter_body
~cont_and_stack_sampler:(fun _cfg _rng_state () ->
Ex_stack_and_cont
{
stack = ((), eos);
stack_type = unit @$ bot;
cont = map_enter_body_code [(Script_int.zero, ())];
})
()
let () =
(*
KMap_exit_body ->
(map_update) -> next
KMap_enter_body (empty case) -> next
KNil
*)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KMap_exit_body
~cont_and_stack_sampler:(fun cfg rng_state ->
let kbody = ICdr (dummy_loc, halt) in
fun () ->
let ty = map int unit in
let key, map = Maps.generate_map_and_key_in_map cfg rng_state in
let cont = KMap_exit_body (kbody, [], map, key, Some ty, KNil) in
Ex_stack_and_cont
{stack = ((), ((), eos)); stack_type = unit @$ unit @$ bot; cont})
()
let () =
(* KMap_head -> KNil *)
continuation_benchmark
~amplification:100
~name:Interpreter_workload.N_KMap_head
~cont_and_stack_sampler:(fun _cfg _rng_state () ->
let cont = KMap_head (Option.some, KNil) in
Ex_stack_and_cont
{stack = ((), ((), eos)); stack_type = unit @$ unit @$ bot; cont})
()
end
let () =
simple_benchmark
~name:Interpreter_workload.N_IEmit
~stack_type:(unit_t @$ bot)
~kinstr:
(IEmit
{
ty = unit_t;
k = halt;
loc = dummy_loc;
tag = Entrypoint_repr.default;
unparsed_ty = Script_repr.unit;
})
()
end