123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190(*
* Copyright (c) 2013-2022 Thomas Gazagnaire <thomas@gazagnaire.org>
* Copyright (c) 2019 Etienne Millon
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)openIrmin.Export_for_backendstypet={root:string;ncommits:int;depth:int;tree_add:int;display:int;clear:bool;gc:int;}typestats={commits:int;size:int;maxrss:int}letsrc=letopenMetricsinlettags=Tags.[]inletdatat=Data.v[int"commits"t.commits;int"size"~unit:"MiB"t.size;int"maxrss"~unit:"MiB"t.maxrss;]inSrc.v"bench"~tags~data(* cli *)openCmdlinerletdeprecated_info=(Term.info[@alert"-deprecated"])letdeprecated_exit=(Term.exit[@alert"-deprecated"])letdeprecated_eval=(Term.eval[@alert"-deprecated"])letlogstyle_rendererlevel=Fmt_tty.setup_std_outputs?style_renderer();Logs.set_levellevel;Logs.set_reporter(Irmin_test.reporter());()letlog=Term.(constlog$Fmt_cli.style_renderer()$Logs_cli.level())letncommits=letdoc=Arg.info~doc:"Number of iterations."["n";"ncommits"]inArg.(value@@optint1000doc)letdepth=letdoc=Arg.info~doc:"Depth of the tree."["d";"depth"]inArg.(value@@optint30doc)lettree_add=letdoc=Arg.info~doc:"Number of tree entries added per commit"["a";"tree-add"]inArg.(value@@optint1000doc)letdisplay=letdoc=Arg.info~doc:"Number of commits after which the stats are displayed."["s";"stats"]inArg.(value@@optint10doc)letgc=letdoc=Arg.info~doc:"Number of commits after which Gc.full_major is called."["gc"]inArg.(value@@optint100doc)letclear=letdoc=Arg.info~doc:"Clear the tree after each commit."["clear"]inArg.(value@@flagdoc)lett=Term.(const(fun()ncommitsdepthtree_adddisplaycleargc->{ncommits;depth;tree_add;display;root=".";clear;gc})$log$ncommits$depth$tree_add$display$clear$gc)moduleMake(Store:Irmin.Generic_key.KVwithtypeSchema.Contents.t=string)=structletinfo()=Store.Info.v~author:"author"~message:"commit message"0Llettimes~n~initf=letrecgoik=ifi=0thenkinitelsego(i-1)(funr->fir>>=k)ingonLwt.returnletpath~depthn=letrecauxacc=function|iwheni=depth->List.rev(string_of_intn::acc)|i->aux(string_of_inti::acc)(i+1)inaux[]0letget_maxrss()=letusage=Rusage.getSELFinlet(/)=Int64.divinInt64.to_int(usage.maxrss/1024L/1024L)letno_tagsx=xletprint_stats~commits~size=letmaxrss=get_maxrss()inletsize=size()inMetrics.addsrcno_tags(funf->f{size;commits;maxrss})letplot_progressnt=Fmt.epr"\rcommits: %4d/%d%!"nt(* init: create a tree with [t.depth] levels and each levels has
[t.tree_add] files + one directory going to the next levele. *)letinittconfig=lettree=Store.Tree.empty()inlet*v=Store.Repo.vconfig>>=Store.maininlet*tree=times~n:t.depth~init:tree(fundepthtree->letpaths=Array.init(t.tree_add+1)(path~depth)intimes~n:t.tree_add~init:tree(funntree->Store.Tree.addtreepaths.(n)"init"))inStore.set_tree_exnv~info[]tree>|=fun()->Fmt.epr"[init done]\n%!"letruntconfigsize=let*r=Store.Repo.vconfiginlet*v=Store.mainrinStore.Tree.reset_counters();letpaths=Array.init(t.tree_add+1)(path~depth:t.depth)inlet*()=times~n:t.ncommits~init:()(funi()->let*tree=Store.get_treev[]inifimodt.gc=0thenGc.full_major();ifimodt.display=0then(plot_progressit.ncommits;print_stats~size~commits:i);let*tree=times~n:t.tree_add~init:tree(funntree->Store.Tree.addtreepaths.(n)(string_of_inti))inStore.set_tree_exnv~info[]tree>|=fun()->ift.clearthenStore.Tree.cleartree)inStore.Repo.closer>|=fun()->Fmt.epr"\n[run done]\n%!"letmaintconfigsize=letroot="_build/_bench"inletconfig=config~rootinletsize()=size~rootinlett={twithroot}inLwt_main.run(inittconfig>>=fun()->runtconfigsize)letmain_termconfigsize=Term.(constmain$t$constconfig$constsize)let()=at_exit(fun()->Fmt.epr"tree counters:\n%a\n%!"Store.Tree.dump_counters())letrun~config~size=letinfo=deprecated_info"Simple benchmark for trees"indeprecated_exit@@deprecated_eval(main_termconfigsize,info)endlet()=Metrics.enable_all();Metrics_gnuplot.set_reporter()