Automatically infer the @PerformanceCritical annotations from the overriden methods

Summary: public
This allows to run the checker and get feedback about potential expensive call stacks without having to annotate first all the methods that are overriding PerofrmanceCritical-annotated methods

Reviewed By: cristianoc

Differential Revision: D2693556

fb-gh-sync-id: cb60278
master
jrm 9 years ago committed by facebook-github-bot-5
parent dcdebbd811
commit d712635feb

@ -8,6 +8,19 @@
*)
module F = Format
type t =
| Direct of Procname.t
| Indirect of Procname.t * t list
let pp fmt tree =
let rec loop stack = function
| Direct pname ->
F.fprintf fmt "%s -> %s" stack (Procname.to_string pname)
| Indirect (pname, l) ->
let stack' = stack ^ " -> " ^ (Procname.to_string pname) in
IList.iter (loop stack') l in
loop "@" tree

@ -11,3 +11,6 @@
type t =
| Direct of Procname.t
| Indirect of Procname.t * t list
(** print the list of call stacks in the tree *)
val pp : Format.formatter -> t -> unit

@ -10,6 +10,9 @@
module L = Logging
let infer_performance_critical_methods = true
let calls_expensive_method =
"CHECKERS_CALLS_EXPENSIVE_METHOD"
@ -45,6 +48,17 @@ let method_is_performance_critical pname =
check_method Annotations.ia_is_performance_critical pname
let method_overrides_performance_critical tenv pname =
let overrides () =
let found = ref false in
PatternMatch.proc_iter_overridden_methods
(fun pn -> found := method_is_performance_critical pn)
tenv pname;
!found in
method_is_performance_critical pname
|| overrides ()
let method_is_expensive pname =
check_method Annotations.ia_is_expensive pname
@ -152,12 +166,17 @@ let check_one_procedure tenv pname pdesc =
let checked_pnames = ref Procname.Set.empty in
Cfg.Procdesc.fold_calls
(collect_expensive_call pdesc checked_pnames) [] pdesc in
update_summary expensive_call_trees pname;
match expensive_call_trees with
| [] -> ()
| call_trees when infer_performance_critical_methods ->
if method_overrides_performance_critical tenv pname then
report_expensive_calls pname pdesc loc call_trees
| call_trees when performance_critical ->
report_expensive_calls pname pdesc loc call_trees
| call_trees ->
update_summary call_trees pname
| _ -> ()
let callback_performance_checker _ get_proc_desc _ tenv pname proc_desc =

@ -12,15 +12,29 @@ package codetoanalyze.java.checkers;
import com.facebook.infer.annotation.Expensive;
import com.facebook.infer.annotation.PerformanceCritical;
class Other {
@Expensive
void expensive() {
}
void callsExpensive1() {
expensive();
}
}
public class ExpensiveCallExample {
Object mObject;
Other mOther;
void nonExpensiveMethod() {}
@Expensive
void expensiveMethod() {
mObject = new Object();
mOther = new Other();
}
void methodWrapper() {
@ -47,4 +61,13 @@ public class ExpensiveCallExample {
object.m5();
}
void callsExpensive2() {
mOther.callsExpensive1();
}
@PerformanceCritical
void longerCallStackToExpensive() {
callsExpensive2();
}
}

@ -33,7 +33,7 @@ public class ExpensiveCallTest {
@BeforeClass
public static void loadResults() throws InterruptedException, IOException {
inferResults =
InferResults.loadCheckersResults(ImmutableCastTest.class, SOURCE_FILE);
InferResults.loadCheckersResults(ExpensiveCallTest.class, SOURCE_FILE);
}
@Test
@ -43,6 +43,7 @@ public class ExpensiveCallTest {
"directlyCallingExpensiveMethod",
"indirectlyCallingExpensiveMethod",
"callingExpensiveMethodFromInterface",
"longerCallStackToExpensive",
};
assertThat(
"Results should contain " + CALLS_EXPENSIVE_METHOD,

Loading…
Cancel
Save