Summary: Add a new command-line option `--per-procedure-parallelism`, to change the granularity of parallelism of the analysis from file to procedure. This is intended for `--reactive` mode where e.g. a single file is changed and the analysis currently uses just one core. When the option is used, the Makefile mechanism is replaced by using forking instead. The parent process does as little allocation as possible, to avoid taxing the kernel. Caveats: - Not active in Java, (issues with camlzip). - Not active in checkers, yet. Example use: ``` infer --reactive --changed-files-index index.txt --per-procedure-parallelism -- analyze ``` Reviewed By: jberdine Differential Revision: D4634884 fbshipit-source-id: e358c18master
parent
f4c424b4cc
commit
ec6a3cf6bb
@ -0,0 +1,69 @@
|
||||
(*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* 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.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
|
||||
module L = Logging
|
||||
module F = Format
|
||||
|
||||
type closure = unit -> unit
|
||||
|
||||
type t = {
|
||||
closures: closure list;
|
||||
continuations: closure Queue.t;
|
||||
}
|
||||
|
||||
type tasks = t
|
||||
|
||||
let create ?(continuation = None) closures =
|
||||
let continuations = match continuation with
|
||||
| None ->
|
||||
Queue.create ()
|
||||
| Some closure ->
|
||||
Queue.singleton closure in
|
||||
{ closures; continuations }
|
||||
|
||||
let empty = { closures = []; continuations = Queue.create () }
|
||||
|
||||
(* Aggregate closures into groups of the given size *)
|
||||
let aggregate ~size t =
|
||||
let group_to_closure group =
|
||||
fun () -> List.iter ~f:(fun closure -> closure ()) group in
|
||||
if size > 1
|
||||
then
|
||||
let groups = List.groupi ~break:(fun n _ _ -> Int.equal (n mod size) 0) t.closures in
|
||||
let closures = List.map ~f:group_to_closure groups in
|
||||
{ t with closures }
|
||||
else
|
||||
t
|
||||
|
||||
let run t =
|
||||
List.iter ~f:(fun f -> f ()) t.closures;
|
||||
Queue.iter ~f:(fun closure -> closure ()) t.continuations
|
||||
|
||||
module Runner = struct
|
||||
type runner =
|
||||
{ pool : Utils.ProcessPool.t;
|
||||
all_continuations : closure Queue.t }
|
||||
|
||||
let create ~jobs =
|
||||
{ pool = Utils.ProcessPool.create ~jobs;
|
||||
all_continuations = Queue.create () }
|
||||
|
||||
let start runner ~tasks =
|
||||
let pool = runner.pool in
|
||||
Queue.enqueue_all runner.all_continuations (Queue.to_list tasks.continuations);
|
||||
List.iter
|
||||
~f:(fun x -> Utils.ProcessPool.start_child ~f:(fun f -> f ()) ~pool x)
|
||||
tasks.closures
|
||||
|
||||
let complete runner =
|
||||
Utils.ProcessPool.wait_all runner.pool;
|
||||
Queue.iter ~f:(fun f -> f ()) runner.all_continuations
|
||||
end
|
@ -0,0 +1,46 @@
|
||||
(*
|
||||
* Copyright (c) 2017 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* 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.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
|
||||
(** A sequence of tasks that can be executed in parallel,
|
||||
with a continuation to be executed at the end *)
|
||||
type t
|
||||
|
||||
type tasks = t
|
||||
|
||||
(** Each task/continuation executes a closure *)
|
||||
type closure = unit -> unit
|
||||
|
||||
(* Aggregate closures into groups of the given size *)
|
||||
val aggregate : size:int -> t -> t
|
||||
|
||||
(** Create tasks with a list of closures to be executed in parallel,
|
||||
and an optional continuation to be executed afterwards *)
|
||||
val create : ?continuation:(closure option) -> closure list -> t
|
||||
|
||||
(** No-op tasks *)
|
||||
val empty : t
|
||||
|
||||
(** Run the closures and continuation *)
|
||||
val run : t -> unit
|
||||
|
||||
module Runner : sig
|
||||
(** A runner accepts new tasks repeatedly for parallel execution *)
|
||||
type runner
|
||||
|
||||
(** Create a runner *)
|
||||
val create: jobs:int -> runner
|
||||
|
||||
(** Start the given tasks with the runner *)
|
||||
val start : runner -> tasks:t -> unit
|
||||
|
||||
(** Complete all the outstanding tasks *)
|
||||
val complete : runner -> unit
|
||||
end
|
Loading…
Reference in new issue