From 66faedbf15d8b04c70770bd07509f087ed2c3b18 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Sat, 21 May 2016 16:54:56 -0700 Subject: [PATCH] Optimize attribute loading Summary: Optimize attribute loading by caching all attributes read from file in memory. This reduces io and allocation rate and raises memory usage. Reviewed By: cristianoc Differential Revision: D3321156 fbshipit-source-id: 37bc6bc --- infer/src/IR/AttributesTable.re | 35 ++++++++++++++++++++++++++++---- infer/src/IR/AttributesTable.rei | 7 +++++-- infer/src/backend/PerfStats.ml | 34 +++++++++++++++---------------- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/infer/src/IR/AttributesTable.re b/infer/src/IR/AttributesTable.re index f43b3516b..08fee41f8 100644 --- a/infer/src/IR/AttributesTable.re +++ b/infer/src/IR/AttributesTable.re @@ -56,10 +56,18 @@ let store_attributes proc_attributes => { } }; -let load_attributes proc_name => { - let attributes_file = res_dir_attr_filename proc_name; - Serialization.from_file serializer attributes_file -}; +let attr_tbl = Procname.Hash.create 16; + +let load_attributes proc_name => + try (Procname.Hash.find attr_tbl proc_name) { + | Not_found => + let attributes_file = res_dir_attr_filename proc_name; + let attr = Serialization.from_file serializer attributes_file; + if (attr != None) { + Procname.Hash.add attr_tbl proc_name attr + }; + attr + }; /** Given a procdesure name, find the file where it is defined and */ @@ -97,3 +105,22 @@ let pname_is_cpp_model callee_pname => DB.file_is_in_cpp_model file | None => false }; + +let stats () => { + let stats = Procname.Hash.stats attr_tbl; + let {Hashtbl.num_bindings: num_bindings, num_buckets, max_bucket_length} = stats; + let serialized_size = lazy (Marshal.data_size (Marshal.to_bytes attr_tbl []) 0 / 1024); + ( + "AttributesTable.attr_tbl", + `Assoc ( + [ + ("num_bindings", `Int num_bindings), + ("num_buckets", `Int num_buckets), + ("max_bucket_length", `Int max_bucket_length) + ] + @ ( + Config.developer_mode ? [("serialized_size_kb", `Int (Lazy.force serialized_size))] : [] + ) + ) + ) +}; diff --git a/infer/src/IR/AttributesTable.rei b/infer/src/IR/AttributesTable.rei index 77f174c07..1d3558c23 100644 --- a/infer/src/IR/AttributesTable.rei +++ b/infer/src/IR/AttributesTable.rei @@ -9,11 +9,11 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ +/** Module to manage the table of attributes. */ open! Utils; -/** Module to manage the table of attributes. */ /** Save .attr file for the procedure into the attributes database. */ let store_attributes: ProcAttributes.t => unit; @@ -32,5 +32,8 @@ let find_tenv_from_class_of_proc: Procname.t => option Tenv.t; /** finding the tenv that corresponds to the class definition. */ let get_correct_type_from_objc_class_name: Mangled.t => option Sil.typ; + /** Returns true if the method is defined as a C++ model */ -let pname_is_cpp_model : Procname.t => bool; +let pname_is_cpp_model: Procname.t => bool; + +let stats: unit => (string, Yojson.json); diff --git a/infer/src/backend/PerfStats.ml b/infer/src/backend/PerfStats.ml index 9d77dadc6..b7c2f48cc 100644 --- a/infer/src/backend/PerfStats.ml +++ b/infer/src/backend/PerfStats.ml @@ -25,23 +25,23 @@ let register_report_at_exit file = let exit_timeofday = Unix.gettimeofday () in let exit_times = Unix.times () in let stats = - `Assoc [ - ("rtime", `Float (exit_timeofday -. initial_timeofday)) ; - ("utime", `Float (exit_times.tms_utime -. initial_times.tms_utime)) ; - ("stime", `Float (exit_times.tms_stime -. initial_times.tms_stime)) ; - ("cutime", `Float (exit_times.tms_cutime -. initial_times.tms_cutime)) ; - ("cstime", `Float (exit_times.tms_cstime -. initial_times.tms_cstime)) ; - ("minor_gb", `Float (words_to_gb gc_stats.minor_words)) ; - ("promoted_gb", `Float (words_to_gb gc_stats.promoted_words)) ; - ("major_gb", `Float (words_to_gb gc_stats.major_words)) ; - ("allocated_gb", `Float (words_to_gb allocated_words)) ; - ("minor_collections", `Int gc_stats.minor_collections) ; - ("major_collections", `Int gc_stats.major_collections) ; - ("compactions", `Int gc_stats.compactions) ; - ("top_heap_gb", `Float (words_to_gb (float_of_int gc_stats.top_heap_words))) ; - ("stack_kb", `Float (words_to_kb (float_of_int gc_stats.stack_size))) ; - ("minor_heap_kb", `Float (words_to_kb (float_of_int gc_ctrl.minor_heap_size))) ; - ] in + `Assoc ([ + ("rtime", `Float (exit_timeofday -. initial_timeofday)) ; + ("utime", `Float (exit_times.tms_utime -. initial_times.tms_utime)) ; + ("stime", `Float (exit_times.tms_stime -. initial_times.tms_stime)) ; + ("cutime", `Float (exit_times.tms_cutime -. initial_times.tms_cutime)) ; + ("cstime", `Float (exit_times.tms_cstime -. initial_times.tms_cstime)) ; + ("minor_gb", `Float (words_to_gb gc_stats.minor_words)) ; + ("promoted_gb", `Float (words_to_gb gc_stats.promoted_words)) ; + ("major_gb", `Float (words_to_gb gc_stats.major_words)) ; + ("allocated_gb", `Float (words_to_gb allocated_words)) ; + ("minor_collections", `Int gc_stats.minor_collections) ; + ("major_collections", `Int gc_stats.major_collections) ; + ("compactions", `Int gc_stats.compactions) ; + ("top_heap_gb", `Float (words_to_gb (float_of_int gc_stats.top_heap_words))) ; + ("stack_kb", `Float (words_to_kb (float_of_int gc_stats.stack_size))) ; + ("minor_heap_kb", `Float (words_to_kb (float_of_int gc_ctrl.minor_heap_size))) + ] @ [AttributesTable.stats ()]) in try let stats_oc = open_out file in Yojson.pretty_to_channel stats_oc stats ;