From f220bfb31d9b4754f109a7f2300fa989dcd09bce Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Fri, 16 May 2025 10:23:15 +0200 Subject: [PATCH 1/4] Compiler: more timing in wasmoo --- compiler/bin-wasm_of_ocaml/compile.ml | 12 +++++++++++- compiler/bin-wasm_of_ocaml/dune | 1 + compiler/lib-wasm/generate.ml | 2 ++ compiler/lib-wasm/wat_output.ml | 20 ++++++++++---------- compiler/lib/timer.ml | 11 ++++++----- compiler/lib/timer.mli | 2 +- 6 files changed, 31 insertions(+), 17 deletions(-) diff --git a/compiler/bin-wasm_of_ocaml/compile.ml b/compiler/bin-wasm_of_ocaml/compile.ml index 6c7bb018c2..52314f7a5f 100644 --- a/compiler/bin-wasm_of_ocaml/compile.ml +++ b/compiler/bin-wasm_of_ocaml/compile.ml @@ -161,19 +161,23 @@ let link_and_optimize @@ fun opt_temp_sourcemap -> (with_runtime_files ~runtime_wasm_files @@ fun runtime_inputs -> + let t = Timer.make ~get_time:Unix.time () in Binaryen.link ~inputs: (({ Binaryen.module_name = "env"; file = runtime_file } :: runtime_inputs) @ List.map ~f:(fun file -> { Binaryen.module_name = "OCaml"; file }) wat_files) ~opt_output_sourcemap:opt_temp_sourcemap ~output_file:temp_file - ()); + (); + if times () then Format.eprintf " binaryen link: %a@." Timer.print t); + Fs.with_intermediate_file (Filename.temp_file "wasm-dce" ".wasm") @@ fun temp_file' -> opt_with Fs.with_intermediate_file (if enable_source_maps then Some (Filename.temp_file "wasm-dce" ".wasm.map") else None) @@ fun opt_temp_sourcemap' -> + let t = Timer.make ~get_time:Unix.time () in let primitives = Binaryen.dead_code_elimination ~dependencies:Runtime_files.dependencies @@ -182,6 +186,8 @@ let link_and_optimize ~input_file:temp_file ~output_file:temp_file' in + if times () then Format.eprintf " binaryen dce: %a@." Timer.print t; + let t = Timer.make ~get_time:Unix.time () in Binaryen.optimize ~profile ~opt_input_sourcemap:opt_temp_sourcemap' @@ -189,6 +195,7 @@ let link_and_optimize ~input_file:temp_file' ~output_file (); + if times () then Format.eprintf " binaryen opt: %a@." Timer.print t; Option.iter ~f:(update_sourcemap ~sourcemap_root ~sourcemap_don't_inline_content) opt_sourcemap_file; @@ -506,6 +513,7 @@ let run in let generated_js = output_gen wat_file (output code ~unit_name:None) in let tmp_wasm_file = Filename.concat tmp_dir "code.wasm" in + let t2 = Timer.make ~get_time:Unix.time () in let primitives = link_and_optimize ~profile @@ -516,6 +524,7 @@ let run [ wat_file ] tmp_wasm_file in + if times () then Format.eprintf " link_and_optimize: %a@." Timer.print t2; let wasm_name = Printf.sprintf "code-%s" @@ -529,6 +538,7 @@ let run Link.Wasm_binary.append_source_map_section ~file:tmp_wasm_file' ~url:(wasm_name ^ ".wasm.map")); + if times () then Format.eprintf "Start building js runtime@."; let js_runtime = let missing_primitives = let l = Link.Wasm_binary.read_imports ~file:tmp_wasm_file' in diff --git a/compiler/bin-wasm_of_ocaml/dune b/compiler/bin-wasm_of_ocaml/dune index 1870a60f7c..e00c918434 100644 --- a/compiler/bin-wasm_of_ocaml/dune +++ b/compiler/bin-wasm_of_ocaml/dune @@ -9,6 +9,7 @@ compiler-libs.common js_of_ocaml-compiler.runtime-files yojson + unix (select findlib_support.ml from diff --git a/compiler/lib-wasm/generate.ml b/compiler/lib-wasm/generate.ml index 3279552e8c..aea667df8d 100644 --- a/compiler/lib-wasm/generate.ml +++ b/compiler/lib-wasm/generate.ml @@ -1318,6 +1318,7 @@ let add_init_function = G.add_init_function let output ch ~enable_source_maps ~context = let t = Timer.make () in let fields = G.output ~context in + if times () then Format.eprintf " fields: %a@." Timer.print t; if enable_source_maps || Debug.find "wat" () then Wat_output.f ch fields else Wasm_output.f ch fields; @@ -1326,5 +1327,6 @@ let output ch ~enable_source_maps ~context = let wasm_output ch ~context = let t = Timer.make () in let fields = G.output ~context in + if times () then Format.eprintf " fields: %a@." Timer.print t; Wasm_output.f ch fields; if times () then Format.eprintf " output: %a@." Timer.print t diff --git a/compiler/lib-wasm/wat_output.ml b/compiler/lib-wasm/wat_output.ml index 334adc30f0..839e0dfda5 100644 --- a/compiler/lib-wasm/wat_output.ml +++ b/compiler/lib-wasm/wat_output.ml @@ -666,10 +666,13 @@ let field ctx st f = | Type [ t ] -> [ type_field st t ] | Type l -> [ List (Atom "rec" :: List.map ~f:(type_field st) l) ] +let times = Debug.find "times" + let f ch fields = + let t = Timer.make () in let st = build_name_tables fields in let ctx = { function_refs = Code.Var.Set.empty } in - let other_fields = List.concat (List.map ~f:(fun f -> field ctx st f) fields) in + let other_fields = List.concat_map ~f:(fun f -> field ctx st f) fields in let funct_decl = let functions = Code.Var.Set.elements ctx.function_refs in if List.is_empty functions @@ -682,12 +685,9 @@ let f ch fields = :: List.map ~f:(index st.func_names) functions) ] in - Format.fprintf - (Format.formatter_of_out_channel ch) - "%a@." - format_sexp - (List - (Atom "module" - :: (List.concat (List.map ~f:(fun i -> import st i) fields) - @ funct_decl - @ other_fields))) + let imports = List.concat_map ~f:(fun i -> import st i) fields in + let sexp = List (Atom "module" :: List.concat [ imports; funct_decl; other_fields ]) in + if times () then Format.eprintf " prepare: %a@." Timer.print t; + let t = Timer.make () in + Format.fprintf (Format.formatter_of_out_channel ch) "%a@." format_sexp sexp; + if times () then Format.eprintf " format: %a@." Timer.print t diff --git a/compiler/lib/timer.ml b/compiler/lib/timer.ml index f598ab8d66..ecf6828880 100644 --- a/compiler/lib/timer.ml +++ b/compiler/lib/timer.ml @@ -18,12 +18,13 @@ open! Stdlib -type t = float +type t = + { get_time : unit -> float + ; start : float + } -let timer = Sys.time +let make ?(get_time = Sys.time) () = { get_time; start = get_time () } -let make () = timer () - -let get t = timer () -. t +let get t = t.get_time () -. t.start let print f t = Format.fprintf f "%.2f" (get t) diff --git a/compiler/lib/timer.mli b/compiler/lib/timer.mli index 763113b1a3..8eea624f1c 100644 --- a/compiler/lib/timer.mli +++ b/compiler/lib/timer.mli @@ -18,7 +18,7 @@ type t -val make : unit -> t +val make : ?get_time:(unit -> float) -> unit -> t val get : t -> float From 8ab75e120ebc99142fe1dad427ec2c1df8a01f52 Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Fri, 16 May 2025 12:03:40 +0200 Subject: [PATCH 2/4] Enable binaryen timings --- compiler/lib-wasm/binaryen.ml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/lib-wasm/binaryen.ml b/compiler/lib-wasm/binaryen.ml index 8b3cfc89e3..0ae3cdb893 100644 --- a/compiler/lib-wasm/binaryen.ml +++ b/compiler/lib-wasm/binaryen.ml @@ -20,10 +20,12 @@ open Stdlib let debug = Debug.find "binaryen" +let times = Debug.find "times" + let command cmdline = let cmdline = String.concat ~sep:" " cmdline in if debug () then Format.eprintf "+ %s@." cmdline; - let res = Sys.command cmdline in + let res = Sys.command ((if times () then "BINARYEN_PASS_DEBUG=1 " else "") ^ cmdline) in if res <> 0 then failwith ("the following command terminated unsuccessfully: " ^ cmdline) let common_options () = @@ -38,7 +40,9 @@ let common_options () = ; "--enable-strings" ] in - if Config.Flag.pretty () then "-g" :: l else l + let l = if Config.Flag.pretty () then "-g" :: l else l in + let l = if false then "--no-validation" :: l else l in + l let opt_flag flag v = match v with From c1f1e0ad8ae0104c86ec6e0a76f83ed9c2655d50 Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Fri, 16 May 2025 12:15:42 +0200 Subject: [PATCH 3/4] Add debug for timing binaryen --- compiler/lib-wasm/binaryen.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/lib-wasm/binaryen.ml b/compiler/lib-wasm/binaryen.ml index 0ae3cdb893..b1e601d06b 100644 --- a/compiler/lib-wasm/binaryen.ml +++ b/compiler/lib-wasm/binaryen.ml @@ -20,7 +20,7 @@ open Stdlib let debug = Debug.find "binaryen" -let times = Debug.find "times" +let times = Debug.find "binaryen-times" let command cmdline = let cmdline = String.concat ~sep:" " cmdline in @@ -41,7 +41,7 @@ let common_options () = ] in let l = if Config.Flag.pretty () then "-g" :: l else l in - let l = if false then "--no-validation" :: l else l in + let l = if times () then "--no-validation" :: l else l in l let opt_flag flag v = From 23a37f47f25e4f44b1a3c03ed5321b31f2efed97 Mon Sep 17 00:00:00 2001 From: Hugo Heuzard Date: Fri, 16 May 2025 12:20:13 +0200 Subject: [PATCH 4/4] make wasm tools faster --- compiler/lib-wasm/binaryen.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/lib-wasm/binaryen.ml b/compiler/lib-wasm/binaryen.ml index b1e601d06b..1903e2e674 100644 --- a/compiler/lib-wasm/binaryen.ml +++ b/compiler/lib-wasm/binaryen.ml @@ -115,9 +115,9 @@ let dead_code_elimination filter_unused_primitives primitives usage_file let optimization_options : Profile.t -> _ = function - | O1 -> [ "-O2"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ] - | O2 -> [ "-O2"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ] - | O3 -> [ "-O3"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ] + | O1 -> [ "-O1"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ] + | O2 -> [ "-O1"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ] + | O3 -> [ "-O2"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ] let optimize ~profile