-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Closed
Labels
Milestone
Description
Hi,
I found an input pattern that can trigger Ω(N^2) running time behavior of ImmutableBiMap.copyOf
, the input is constructed and tested using the following code:
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.ImmutableBiMap;
import java.util.ArrayList;
import java.util.Random;
public class GuavaImmutableBiMap {
public static void main(String[] args) {
ArrayList<ImmutablePair<Integer, Integer>> pattern = generateInput(600);
ArrayList<ImmutablePair<Integer, Integer>> randomInput = randomInput(600);
int testNum = 4000;
long start;
double timeUse;
start = System.nanoTime();
for(int i = 0; i < testNum; i++) {
ImmutableBiMap.copyOf(randomInput);
}
timeUse = (System.nanoTime() - start)/1e9;
System.out.println("Random input time use: " + timeUse + "s.");
start = System.nanoTime();
for(int i = 0; i < testNum; i++) {
ImmutableBiMap.copyOf(pattern);
}
timeUse = (System.nanoTime() - start)/1e9;
System.out.println("Pattern time use: " + timeUse + "s.");
}
public static ArrayList<ImmutablePair<Integer, Integer>> generateInput(int size){
int s1 = 475;
ImmutablePair<Integer, Integer> s2 = new ImmutablePair<>(271,212);
ArrayList<ImmutablePair<Integer, Integer>> s4 = new ArrayList<>();
s4.add(s2);
for (int i = 0; i < size; i ++){
s1 = ((99*302*486) | 475) + 142 + (s1-1);
s2 = new ImmutablePair<>(s2.right, s1 << 353);
s4.add(s2);
}
return s4;
}
public static ArrayList<ImmutablePair<Integer, Integer>> randomInput(int size){
Random rand = new Random(1);
ArrayList<ImmutablePair<Integer, Integer>> list = new ArrayList<>();
for (int i = 0; i < size; i ++){
list.add(new ImmutablePair<>(rand.nextInt(), rand.nextInt()));
}
return list;
}
}
On my machine, when running with -Xint
, I got the following result:
Random input time use: 4.183300757s.
Pattern time use: 243.795791197s.
It's about 60X slowdown.
When running without -Xint
and increase testNum from 4000 to 40000 (to reduce noise), the result was:
Random input time use: 0.816171511s.
Pattern time use: 38.315509883s.
I also tried to fit the performance-inputSize relationship, the result is a quadratic curve:
Note that this input pattern I found only have this quadratic behavior when size < 600, but this is due to a current technical limitation of our fuzzing tool used to find this input pattern, and we suspect there exist patterns that can scale to larger sizes.
liach