From b6b2004db1056d628a4d8c30dd61b14fb18cf876 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 2 Jul 2009 12:23:08 +0100 Subject: [PATCH] Memoize the output of pod2text function in the generator. This speeds up the generator greatly. --- .gitignore | 1 + src/generator.ml | 69 ++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 4655de5..dfdc96b 100644 --- a/.gitignore +++ b/.gitignore @@ -142,6 +142,7 @@ ruby/bindtests.rb ruby/ext/guestfs/_guestfs.c ruby/ext/guestfs/extconf.h ruby/ext/guestfs/mkmf.log +src/.pod2text.data src/MAX_PROC_NR src/guestfs-actions.c src/guestfs-actions.h diff --git a/src/generator.ml b/src/generator.ml index 766650f..29e6651 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -2889,6 +2889,17 @@ type callt = | CallInt of int | CallBool of bool +(* Used to memoize the result of pod2text. *) +let pod2text_memo_filename = "src/.pod2text.data" +let pod2text_memo : ((int * string * string), string list) Hashtbl.t = + try + let chan = open_in pod2text_memo_filename in + let v = input_value chan in + close_in chan; + v + with + _ -> Hashtbl.create 13 + (* Useful functions. * Note we don't want to use any external OCaml libraries which * makes this a bit harder than it should be. @@ -7032,32 +7043,42 @@ class GuestFS: (* Useful if you need the longdesc POD text as plain text. Returns a * list of lines. * - * This is the slowest thing about autogeneration. + * Because this is very slow (the slowest part of autogeneration), + * we memoize the results. *) and pod2text ~width name longdesc = - let filename, chan = Filename.open_temp_file "gen" ".tmp" in - fprintf chan "=head1 %s\n\n%s\n" name longdesc; - close_out chan; - let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in - let chan = Unix.open_process_in cmd in - let lines = ref [] in - let rec loop i = - let line = input_line chan in - if i = 1 then (* discard the first line of output *) - loop (i+1) - else ( - let line = triml line in - lines := line :: !lines; - loop (i+1) - ) in - let lines = try loop 1 with End_of_file -> List.rev !lines in - Unix.unlink filename; - match Unix.close_process_in chan with - | Unix.WEXITED 0 -> lines - | Unix.WEXITED i -> - failwithf "pod2text: process exited with non-zero status (%d)" i - | Unix.WSIGNALED i | Unix.WSTOPPED i -> - failwithf "pod2text: process signalled or stopped by signal %d" i + let key = width, name, longdesc in + try Hashtbl.find pod2text_memo key + with Not_found -> + let filename, chan = Filename.open_temp_file "gen" ".tmp" in + fprintf chan "=head1 %s\n\n%s\n" name longdesc; + close_out chan; + let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in + let chan = Unix.open_process_in cmd in + let lines = ref [] in + let rec loop i = + let line = input_line chan in + if i = 1 then (* discard the first line of output *) + loop (i+1) + else ( + let line = triml line in + lines := line :: !lines; + loop (i+1) + ) in + let lines = try loop 1 with End_of_file -> List.rev !lines in + Unix.unlink filename; + (match Unix.close_process_in chan with + | Unix.WEXITED 0 -> () + | Unix.WEXITED i -> + failwithf "pod2text: process exited with non-zero status (%d)" i + | Unix.WSIGNALED i | Unix.WSTOPPED i -> + failwithf "pod2text: process signalled or stopped by signal %d" i + ); + Hashtbl.add pod2text_memo key lines; + let chan = open_out pod2text_memo_filename in + output_value chan pod2text_memo; + close_out chan; + lines (* Generate ruby bindings. *) and generate_ruby_c () = -- 1.8.3.1