From 5c2f44cbeb2aa0e758447364ee9712c2a02d9da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezgi=20=C3=87i=C3=A7ek?= Date: Mon, 6 Jul 2020 05:47:04 -0700 Subject: [PATCH] [cost] Add cost models for Collection.addAll Summary: `addAll` adds elements one by one and hence takes linear time. We didn't have a model for this and considered it O(1). Reviewed By: skcho Differential Revision: D22375157 fbshipit-source-id: 65b82bfae --- infer/src/cost/costModels.ml | 6 ++++++ .../codetoanalyze/java/performance/ArrayListTest.java | 4 ++++ .../tests/codetoanalyze/java/performance/cost-issues.exp | 9 +++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/infer/src/cost/costModels.ml b/infer/src/cost/costModels.ml index 6db29af39..1a696a648 100644 --- a/infer/src/cost/costModels.ml +++ b/infer/src/cost/costModels.ml @@ -170,6 +170,12 @@ module Call = struct $+...$--> BoundsOfArray.logarithmic_length ~of_function:"Arrays.binarySearch" ; +PatternMatch.implements_arrays &:: "copyOf" <>$ any_arg $+ capt_exp $+...$--> linear ~of_function:"Arrays.copyOf" + ; +PatternMatch.implements_collection + &:: "addAll" <>$ any_arg $+ any_arg $+ capt_exp + $--> BoundsOfCollection.linear_length ~of_function:"Collection.addAll" + ; +PatternMatch.implements_collection + &:: "addAll" <>$ any_arg $+ capt_exp + $--> BoundsOfCollection.linear_length ~of_function:"Collection.addAll" ; +PatternMatch.implements_collections &:: "copy" <>$ capt_exp $+...$--> BoundsOfCollection.linear_length ~of_function:"Collections.copy" diff --git a/infer/tests/codetoanalyze/java/performance/ArrayListTest.java b/infer/tests/codetoanalyze/java/performance/ArrayListTest.java index 30803178b..8b11c0a5f 100644 --- a/infer/tests/codetoanalyze/java/performance/ArrayListTest.java +++ b/infer/tests/codetoanalyze/java/performance/ArrayListTest.java @@ -249,6 +249,10 @@ public class ArrayListTest { for (int i = 0; i < slist.size(); i++) {} } + void add_all_linear(ArrayList l1, ArrayList l2) { + l1.addAll(l2); + } + void sort_comparator_nlogn(ArrayList people) { java.util.Collections.sort(people, new LexicographicComparator()); } diff --git a/infer/tests/codetoanalyze/java/performance/cost-issues.exp b/infer/tests/codetoanalyze/java/performance/cost-issues.exp index 4eaea70f7..615697d77 100644 --- a/infer/tests/codetoanalyze/java/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/java/performance/cost-issues.exp @@ -31,9 +31,10 @@ codetoanalyze/java/performance/ArrayCost.java, ArrayCost.isPowOfTwo_constant(int codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest$Elt.(ArrayListTest), 6, OnUIThread:false, [] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest$Elt.get_boolean():boolean, 4, OnUIThread:false, [] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.(), 15, OnUIThread:false, [] +codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.add_all_linear(java.util.ArrayList,java.util.ArrayList):void, 4 + l2.length, OnUIThread:false, [{l2.length},Modeled call to Collection.addAll] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.array_get_elem_constant():void, 81, OnUIThread:false, [] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_add3_overrun_constant():void, 27, OnUIThread:false, [] -codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_addAll_constant():void, 39, OnUIThread:false, [] +codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_addAll_constant():void, 41, OnUIThread:false, [] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_add_in_loop_constant():void, 174, OnUIThread:false, [] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_add_in_nested_loop_constant_constant():void, 1774, OnUIThread:false, [] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_add_then_loop_constant():void, 187, OnUIThread:false, [] @@ -52,8 +53,8 @@ codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.arraylist_set_u codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.boolean_control_var_linear():void, 7 + 19 ⋅ this.arr.length + 4 ⋅ (this.arr.length + 1), OnUIThread:false, [{this.arr.length + 1},Loop,{this.arr.length},Loop] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.call_init_with_put_linear(java.util.ArrayList):void, 22 + 8 ⋅ a.length + 13 ⋅ a.length + 3 ⋅ (a.length + 1) + 3 ⋅ (a.length + 1), OnUIThread:false, [{a.length + 1},Call to HashMap ArrayListTest.init_with_put_linear(ArrayList),Loop,{a.length + 1},Loop,{a.length},Call to HashMap ArrayListTest.init_with_put_linear(ArrayList),Loop,{a.length},Loop] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.call_sortArrayList(java.util.ArrayList):void, 4 + list.length × log(list.length), OnUIThread:false, [{list.length},Call to void ArrayListTest.sortArrayList(ArrayList),Modeled call to Collections.sort,{list.length},Call to void ArrayListTest.sortArrayList(ArrayList),Modeled call to Collections.sort] -codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.constructor_add_all(java.util.ArrayList,java.util.ArrayList):void, 13 + 5 ⋅ (l.length + list.length) + 3 ⋅ (l.length + list.length + 1), OnUIThread:false, [{l.length + list.length + 1},Loop,{l.length + list.length},Loop] -codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.constructor_add_all_sym(java.util.ArrayList,java.util.ArrayList):void, 13 + 5 ⋅ (l.length + list.length) + 3 ⋅ (l.length + list.length + 1), OnUIThread:false, [{l.length + list.length + 1},Loop,{l.length + list.length},Loop] +codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.constructor_add_all(java.util.ArrayList,java.util.ArrayList):void, 12 + l.length + 5 ⋅ (l.length + list.length) + 3 ⋅ (l.length + list.length + 1), OnUIThread:false, [{l.length + list.length + 1},Loop,{l.length + list.length},Loop,{l.length},Modeled call to Collection.addAll] +codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.constructor_add_all_sym(java.util.ArrayList,java.util.ArrayList):void, 12 + l.length + 5 ⋅ (l.length + list.length) + 3 ⋅ (l.length + list.length + 1), OnUIThread:false, [{l.length + list.length + 1},Loop,{l.length + list.length},Loop,{l.length},Modeled call to Collection.addAll] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.constructor_linear(java.util.ArrayList):void, 9 + 5 ⋅ list.length + 3 ⋅ (list.length + 1), OnUIThread:false, [{list.length + 1},Loop,{list.length},Loop] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.constructor_modify(java.util.ArrayList):void, 21 + 5 ⋅ (list.length + 4) + 3 ⋅ (list.length + 5), OnUIThread:false, [{list.length + 5},Loop,{list.length + 4},Loop] codetoanalyze/java/performance/ArrayListTest.java, ArrayListTest.empty_list_constant(int):void, 12, OnUIThread:false, [] @@ -253,7 +254,7 @@ codetoanalyze/java/performance/ListTest.java, ListTest.call_list_files_linear(ja codetoanalyze/java/performance/ListTest.java, ListTest.indexOfImpl_linear(java.util.List,java.lang.Object):int, 14 + 11 ⋅ list.length + 3 ⋅ (list.length + 1), OnUIThread:false, [{list.length + 1},Loop,{list.length},Loop] codetoanalyze/java/performance/ListTest.java, ListTest.iter_multiple_list1_linear(java.util.List,java.util.List):void, 19 + 12 ⋅ (l2.length + l1.length) + 3 ⋅ (l2.length + l1.length + 1), OnUIThread:false, [{l2.length + l1.length + 1},Loop,{l2.length + l1.length},Loop] codetoanalyze/java/performance/ListTest.java, ListTest.iter_multiple_list2_linear(java.util.List,java.util.List):void, 16 + 8 ⋅ (l2.length + l1.length) + 3 ⋅ (l2.length + l1.length + 1), OnUIThread:false, [{l2.length + l1.length + 1},Loop,{l2.length + l1.length},Loop] -codetoanalyze/java/performance/ListTest.java, ListTest.iter_multiple_list3_linear(java.util.List,java.util.List,java.util.List):void, 20 + 8 ⋅ (l2.length + l1.length + a.length) + 3 ⋅ (l2.length + l1.length + a.length + 1), OnUIThread:false, [{l2.length + l1.length + a.length + 1},Loop,{l2.length + l1.length + a.length},Loop] +codetoanalyze/java/performance/ListTest.java, ListTest.iter_multiple_list3_linear(java.util.List,java.util.List,java.util.List):void, 19 + (l2.length + l1.length) + 8 ⋅ (l2.length + l1.length + a.length) + 3 ⋅ (l2.length + l1.length + a.length + 1), OnUIThread:false, [{l2.length + l1.length + a.length + 1},Loop,{l2.length + l1.length + a.length},Loop,{l2.length + l1.length},Modeled call to Collection.addAll] codetoanalyze/java/performance/ListTest.java, ListTest.iter_my_own_obj(java.util.List):void, 22 + 14 ⋅ a.length + 6 ⋅ a.length + 3 ⋅ (a.length + 1), OnUIThread:false, [{a.length + 1},Loop,{a.length},Loop,{a.length},Loop] codetoanalyze/java/performance/ListTest.java, ListTest.iter_relation_with_var(java.util.List):void, 11 + 10 ⋅ a.length + 5 ⋅ a.length + 3 ⋅ (a.length + 1), OnUIThread:false, [{a.length + 1},Loop,{a.length},Loop,{a.length},Loop] codetoanalyze/java/performance/ListTest.java, ListTest.iterate_elements_linear(java.util.List):void, 6 + 5 ⋅ l.length + 3 ⋅ (l.length + 1), OnUIThread:false, [{l.length + 1},Loop,{l.length},Loop]