Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file cache_memory_helpers.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2021 Nomadic Labs, <contact@nomadic-labs.com> *)(* *)(* 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. *)(* *)(*****************************************************************************)moduletypeSNodes=sigtypet=privateintvalzero:tvalone:t[@@ocaml.warning"-32"]valsucc:t->tvaladd:t->t->tvalto_int:t->intend(** The [Nodes] module is used to count the number of computation steps
performed when evaluating the size of the in-memory graph corresponding
to an OCaml value.
In first approximation, the value of type [Nodes.t] threaded through
{!expr_size} below and through the module {!Script_typed_ir_size}
is meant to match the number of recursive calls in the [traverse]
functions of {!Script_typed_ir} and in that of {!node_size}.
The assumption is that there's a bounded amount of work performed between
two such recursive calls, hence that the total work is bounded above
by something proportional to the [Nodes.t] accumulator.
Computations on values of type [Nodes.t] do not overflow, as they
are bounded above by the number of nodes traversed when computing
an OCaml value.
*)moduleNodes:SNodes=structtypet=intletzero=0letone=1letsuccx=x+1letaddxy=x+yletto_intx=xend(** {2 Helpers to deal with computing the in-memory size of values} *)typesint=Saturation_repr.may_saturateSaturation_repr.ttypenodes_and_size=Nodes.t*sintlet(!!)=Saturation_repr.safe_intlet(+!)=Saturation_repr.addlet(+?)sx=Saturation_repr.adds!!xlet(*?)sx=Saturation_repr.muls!!xlet(/?)sx=Saturation_repr.edivs!!xlet(++)(n1,s1)(n2,s2)=(Nodes.addn1n2,s1+!s2)letzero=(Nodes.zero,!!0)letword_size=!!8letheader_size=word_sizeletint32_size=header_size+!word_sizeletint64_size=header_size+!(word_size*?2)leth1w=header_size+!word_sizeleth2w=header_size+!(word_size*?2)leth3w=header_size+!(word_size*?3)leth4w=header_size+!(word_size*?4)leth5w=header_size+!(word_size*?5)lethh3w=(word_size*?3)+!(header_size*?2)lethh6w=(word_size*?6)+!(header_size*?2)lethh8w=(word_size*?8)+!(header_size*?2)letz_sizez=letnumbits=Z.numbitszin(*
Z does not seem to have a canonical representation of numbers.
Hence, even though we observed that 24 works in many cases we
sometimes meet numbers with a larger size, hence we use 32 instead
of 24 in the following formula.
*)ifCompare.Int.(numbits<=62)then!!0else(word_size*?Z.sizez)+?32letstring_size_genlen=header_size+?(len+(8-(lenmod8)))letbytes_sizeb=string_size_gen(Bytes.lengthb)letstring_sizes=string_size_gen(String.lengths)letblake2b_hash_size=h1w+!string_size_gen20letpublic_key_hash_in_memory_size=h1w+!blake2b_hash_sizeletret_adding(nodes,size)added=(nodes,size+!added)letret_succ_adding(nodes,size)added=(Nodes.succnodes,size+!added)letret_succ(nodes,size)=(Nodes.succnodes,size)letoption_sizesomex=letsomex=h1w+!somexinOption.fold~none:!!0~somexletoption_size_vecsomex=letsomex=ret_adding(somex)h1winOption.fold~none:zero~somexletlist_cell_sizeelt_size=header_size+!word_size+!word_size+!elt_size[@@ocaml.inlinealways]letlist_fold_sizeelt_sizelist=List.fold_left(funaccuelt->ret_succ_adding(accu++elt_sizeelt)h2w)zerolistletboxed_tup2xy=header_size+!word_size+!word_size+!x+!y[@@ocaml.inlinealways]letnode_size=letopenMichelinein(* An OCaml list item occupies 3 words of memory: one for the (::)
constructor, one for the item itself (head) and one for the
remainder of the list (tail). *)letlist_sizesns=word_size*?(List.lengthsns*3)inletannotation_sizea=List.fold_left(funaccus->ret_succ_addingaccu(h2w+!string_sizes))zeroainletinternal_node_size=function|Int(_,z)->(Nodes.one,h2w+!z_sizez)|String(_,s)->(Nodes.one,h2w+!string_sizes)|Bytes(_,s)->(Nodes.one,h2w+!bytes_sizes)|Prim(_,_,args,a)->ret_succ_adding(annotation_sizea)(list_sizeargs+!h4w)|Seq(_,terms)->(Nodes.one,list_sizeterms+!h2w)infunnode->Script_repr.foldnodezero@@funaccunode->accu++internal_node_sizenodeletexpr_sizeexpr=node_size(Micheline.rootexpr)