From 2762c411b689c323c080498c6384d48417475463 Mon Sep 17 00:00:00 2001 From: Fernando Gasperi Jabalera Date: Wed, 25 Mar 2020 09:31:56 -0700 Subject: [PATCH] Use LRUCache in Ondemand.LocalCache Summary: Use the an LRUCache in Ondemand.LocalCache to avoid clearing it after every toplevel analysis. Reviewed By: ngorogiannis Differential Revision: D20281932 fbshipit-source-id: 752c8e1ea --- infer/man/man1/infer-full.txt | 3 +++ infer/src/backend/InferAnalyze.ml | 11 +++++------ infer/src/backend/ondemand.ml | 15 ++++++++++----- infer/src/base/Config.ml | 7 +++++++ infer/src/base/Config.mli | 2 ++ infer/src/istd/LRUHashtbl.ml | 12 ++++++++++++ infer/src/istd/LRUHashtbl.mli | 2 ++ 7 files changed, 41 insertions(+), 11 deletions(-) diff --git a/infer/man/man1/infer-full.txt b/infer/man/man1/infer-full.txt index 251a95901..d15188648 100644 --- a/infer/man/man1/infer-full.txt +++ b/infer/man/man1/infer-full.txt @@ -1739,6 +1739,9 @@ INTERNAL OPTIONS Deactivates: Use the multirange subtyping domain (Conversely: --subtype-multirange) + --summaries-caches-max-size int + The maximum amount of elements the summaries LRU caches can hold + --symops-per-iteration int Set the number of symbolic operations per iteration (see --iterations) diff --git a/infer/src/backend/InferAnalyze.ml b/infer/src/backend/InferAnalyze.ml index 738200ff6..d0f88a9ea 100644 --- a/infer/src/backend/InferAnalyze.ml +++ b/infer/src/backend/InferAnalyze.ml @@ -13,13 +13,12 @@ module F = Format module L = Logging module CLOpt = CommandLineOption -let clear_caches () = - Ondemand.LocalCache.clear () ; - Summary.OnDisk.clear_cache () ; - Procname.SQLite.clear_cache () ; - BufferOverrunUtils.clear_cache () +let clear_caches_except_lrus () = + Summary.OnDisk.clear_cache () ; Procname.SQLite.clear_cache () ; BufferOverrunUtils.clear_cache () +let clear_caches () = Ondemand.LocalCache.clear () ; clear_caches_except_lrus () + let analyze_target : (SchedulerTypes.target, Procname.t) Tasks.doer = let analyze_source_file exe_env source_file = if Topl.is_active () then DB.Results_dir.init (Topl.sourcefile ()) ; @@ -52,7 +51,7 @@ let analyze_target : (SchedulerTypes.target, Procname.t) Tasks.doer = fun target -> let exe_env = Exe_env.mk () in (* clear cache for each source file to avoid it growing unboundedly *) - clear_caches () ; + clear_caches_except_lrus () ; match target with | Procname procname -> analyze_proc_name exe_env procname diff --git a/infer/src/backend/ondemand.ml b/infer/src/backend/ondemand.ml index 5ef2e5275..ab3f4da6b 100644 --- a/infer/src/backend/ondemand.ml +++ b/infer/src/backend/ondemand.ml @@ -15,20 +15,25 @@ module F = Format let exe_env_ref = ref None module LocalCache = struct - let results = lazy (Procname.Hash.create 128) + let results = + lazy + (Procname.LRUHash.create ~initial_size:Config.summaries_caches_max_size + ~max_size:Config.summaries_caches_max_size) - let clear () = Procname.Hash.clear (Lazy.force results) - let remove pname = Procname.Hash.remove (Lazy.force results) pname + let clear () = Procname.LRUHash.clear (Lazy.force results) + + let remove pname = Procname.LRUHash.remove (Lazy.force results) pname let get proc_name = - let summ_opt_opt = Procname.Hash.find_opt (Lazy.force results) proc_name in + let summ_opt_opt = Procname.LRUHash.find_opt (Lazy.force results) proc_name in if Option.is_some summ_opt_opt then BackendStats.incr_ondemand_local_cache_hits () else BackendStats.incr_ondemand_local_cache_misses () ; summ_opt_opt - let add proc_name summary_option = Procname.Hash.add (Lazy.force results) proc_name summary_option + let add proc_name summary_option = + Procname.LRUHash.replace (Lazy.force results) proc_name summary_option end let set_exe_env (env : Exe_env.t) = exe_env_ref := Some env diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index b31983d20..a83478b9b 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -2165,6 +2165,11 @@ and subtype_multirange = "Use the multirange subtyping domain" +and summaries_caches_max_size = + CLOpt.mk_int ~long:"summaries-caches-max-size" ~default:500 + "The maximum amount of elements the summaries LRU caches can hold" + + and symops_per_iteration = CLOpt.mk_int_opt ~deprecated:["symops_per_iteration"] ~long:"symops-per-iteration" ~meta:"int" "Set the number of symbolic operations per iteration (see $(b,--iterations))" @@ -3018,6 +3023,8 @@ and starvation_whole_program = !starvation_whole_program and subtype_multirange = !subtype_multirange +and summaries_caches_max_size = !summaries_caches_max_size + and custom_symbols = (* Convert symbol lists to regexps just once, here *) match !custom_symbols with diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index c4b170745..4465bd0ea 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -606,6 +606,8 @@ val starvation_whole_program : bool val subtype_multirange : bool +val summaries_caches_max_size : int + val symops_per_iteration : int option val test_determinator : bool diff --git a/infer/src/istd/LRUHashtbl.ml b/infer/src/istd/LRUHashtbl.ml index 9b98f198a..b9177d13a 100644 --- a/infer/src/istd/LRUHashtbl.ml +++ b/infer/src/istd/LRUHashtbl.ml @@ -20,6 +20,8 @@ module type S = sig val replace : 'a t -> key -> 'a -> unit + val remove : 'a t -> key -> unit + val clear : 'a t -> unit val pp : @@ -55,6 +57,8 @@ module Make (Key : Hashtbl.HashedType) = struct let use {list} n = Doubly_linked.move_to_front list n + let remove {list} n = Doubly_linked.remove list n + let clear {list} = Doubly_linked.clear list end @@ -79,6 +83,14 @@ module Make (Key : Hashtbl.HashedType) = struct Hash.replace map k (v, n) + let remove {map; lru} k = + match Hash.find_opt map k with + | None -> + () + | Some (_, n) -> + LRU.remove lru n ; Hash.remove map k + + let clear {map; lru} = Hash.clear map ; LRU.clear lru let pp ~pp_key ~pp_v f {map} = diff --git a/infer/src/istd/LRUHashtbl.mli b/infer/src/istd/LRUHashtbl.mli index 62ad13c87..a04ab1bbc 100644 --- a/infer/src/istd/LRUHashtbl.mli +++ b/infer/src/istd/LRUHashtbl.mli @@ -20,6 +20,8 @@ module type S = sig val replace : 'a t -> key -> 'a -> unit + val remove : 'a t -> key -> unit + val clear : 'a t -> unit val pp :