1 /*
2  * Copyright (C) 2012 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkState;
20 
21 import com.google.common.base.Equivalence;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashSet;
25 import java.util.LinkedHashSet;
26 import java.util.Map;
27 import java.util.Queue;
28 import java.util.Random;
29 import java.util.Set;
30 import java.util.SortedMap;
31 import java.util.TreeSet;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.ConcurrentMap;
34 import java.util.concurrent.ConcurrentSkipListMap;
35 
36 /**
37  * Helper classes for various benchmarks.
38  *
39  * @author Christopher Swenson
40  */
41 final class BenchmarkHelpers {
42   /** So far, this is the best way to test various implementations of {@link Set} subclasses. */
43   public interface CollectionsImplEnum {
create(Collection<E> contents)44     <E extends Comparable<E>> Collection<E> create(Collection<E> contents);
45 
name()46     String name();
47   }
48 
49   public interface MapsImplEnum {
create(Map<K, V> contents)50     <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> contents);
51 
name()52     String name();
53   }
54 
55   public interface InternerImplEnum {
create(Collection<E> contents)56     <E> Interner<E> create(Collection<E> contents);
57 
name()58     String name();
59   }
60 
61   public enum SetImpl implements CollectionsImplEnum {
62     HashSetImpl {
63       @Override
create(Collection<E> contents)64       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
65         return new HashSet<E>(contents);
66       }
67     },
68     LinkedHashSetImpl {
69       @Override
create(Collection<E> contents)70       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
71         return new LinkedHashSet<E>(contents);
72       }
73     },
74     TreeSetImpl {
75       @Override
create(Collection<E> contents)76       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
77         return new TreeSet<E>(contents);
78       }
79     },
80     UnmodifiableSetImpl {
81       @Override
create(Collection<E> contents)82       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
83         return Collections.unmodifiableSet(new HashSet<E>(contents));
84       }
85     },
86     SynchronizedSetImpl {
87       @Override
create(Collection<E> contents)88       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
89         return Collections.synchronizedSet(new HashSet<E>(contents));
90       }
91     },
92     ImmutableSetImpl {
93       @Override
create(Collection<E> contents)94       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
95         return ImmutableSet.copyOf(contents);
96       }
97     },
98     ImmutableSortedSetImpl {
99       @Override
create(Collection<E> contents)100       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
101         return ImmutableSortedSet.copyOf(contents);
102       }
103     },
104     ContiguousSetImpl {
105       @Override
create(Collection<E> contents)106       public <E extends Comparable<E>> Set<E> create(Collection<E> contents) {
107         return ContiguousSet.copyOf(contents);
108       }
109     },
110     ;
111   }
112 
113   public enum ListMultimapImpl {
114     ArrayListMultimapImpl {
115       @Override
create(Multimap<K, V> contents)116       <K, V> ListMultimap<K, V> create(Multimap<K, V> contents) {
117         return ArrayListMultimap.create(contents);
118       }
119     },
120     LinkedListMultimapImpl {
121       @Override
create(Multimap<K, V> contents)122       <K, V> ListMultimap<K, V> create(Multimap<K, V> contents) {
123         return LinkedListMultimap.create(contents);
124       }
125     },
126     ImmutableListMultimapImpl {
127       @Override
create(Multimap<K, V> contents)128       <K, V> ListMultimap<K, V> create(Multimap<K, V> contents) {
129         return ImmutableListMultimap.copyOf(contents);
130       }
131     };
132 
create(Multimap<K, V> contents)133     abstract <K, V> ListMultimap<K, V> create(Multimap<K, V> contents);
134   }
135 
136   public enum RangeSetImpl {
137     TreeRangeSetImpl {
138       @Override
create(RangeSet<K> contents)139       <K extends Comparable<K>> RangeSet<K> create(RangeSet<K> contents) {
140         return TreeRangeSet.create(contents);
141       }
142     },
143     ImmutableRangeSetImpl {
144       @Override
create(RangeSet<K> contents)145       <K extends Comparable<K>> RangeSet<K> create(RangeSet<K> contents) {
146         return ImmutableRangeSet.copyOf(contents);
147       }
148     };
149 
create(RangeSet<K> contents)150     abstract <K extends Comparable<K>> RangeSet<K> create(RangeSet<K> contents);
151   }
152 
153   public enum SetMultimapImpl {
154     HashMultimapImpl {
155       @Override
create( Multimap<K, V> contents)156       <K extends Comparable<K>, V extends Comparable<V>> SetMultimap<K, V> create(
157           Multimap<K, V> contents) {
158         return HashMultimap.create(contents);
159       }
160     },
161     LinkedHashMultimapImpl {
162       @Override
create( Multimap<K, V> contents)163       <K extends Comparable<K>, V extends Comparable<V>> SetMultimap<K, V> create(
164           Multimap<K, V> contents) {
165         return LinkedHashMultimap.create(contents);
166       }
167     },
168     TreeMultimapImpl {
169       @Override
create( Multimap<K, V> contents)170       <K extends Comparable<K>, V extends Comparable<V>> SetMultimap<K, V> create(
171           Multimap<K, V> contents) {
172         return TreeMultimap.create(contents);
173       }
174     },
175     ImmutableSetMultimapImpl {
176       @Override
create( Multimap<K, V> contents)177       <K extends Comparable<K>, V extends Comparable<V>> SetMultimap<K, V> create(
178           Multimap<K, V> contents) {
179         return ImmutableSetMultimap.copyOf(contents);
180       }
181     };
182 
create( Multimap<K, V> contents)183     abstract <K extends Comparable<K>, V extends Comparable<V>> SetMultimap<K, V> create(
184         Multimap<K, V> contents);
185   }
186 
187   public enum MapImpl implements MapsImplEnum {
188     HashMapImpl {
189       @Override
create(Map<K, V> map)190       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
191         return Maps.newHashMap(map);
192       }
193     },
194     LinkedHashMapImpl {
195       @Override
create(Map<K, V> map)196       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
197         return Maps.newLinkedHashMap(map);
198       }
199     },
200     ConcurrentHashMapImpl {
201       @Override
create(Map<K, V> map)202       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
203         return new ConcurrentHashMap<>(map);
204       }
205     },
206     ImmutableMapImpl {
207       @Override
create(Map<K, V> map)208       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
209         return ImmutableMap.copyOf(map);
210       }
211     },
212     MapMakerStrongKeysStrongValues {
213       @Override
create(Map<K, V> map)214       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
215         // We use a "custom" equivalence to force MapMaker to make a MapMakerInternalMap.
216         ConcurrentMap<K, V> newMap = new MapMaker().keyEquivalence(Equivalence.equals()).makeMap();
217         checkState(newMap instanceof MapMakerInternalMap);
218         newMap.putAll(map);
219         return newMap;
220       }
221     },
222     MapMakerStrongKeysWeakValues {
223       @Override
create(Map<K, V> map)224       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
225         ConcurrentMap<K, V> newMap = new MapMaker().weakValues().makeMap();
226         checkState(newMap instanceof MapMakerInternalMap);
227         newMap.putAll(map);
228         return newMap;
229       }
230     },
231     MapMakerWeakKeysStrongValues {
232       @Override
create(Map<K, V> map)233       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
234         ConcurrentMap<K, V> newMap = new MapMaker().weakKeys().makeMap();
235         checkState(newMap instanceof MapMakerInternalMap);
236         newMap.putAll(map);
237         return newMap;
238       }
239     },
240     MapMakerWeakKeysWeakValues {
241       @Override
create(Map<K, V> map)242       public <K extends Comparable<K>, V> Map<K, V> create(Map<K, V> map) {
243         ConcurrentMap<K, V> newMap = new MapMaker().weakKeys().weakValues().makeMap();
244         checkState(newMap instanceof MapMakerInternalMap);
245         newMap.putAll(map);
246         return newMap;
247       }
248     };
249   }
250 
251   enum SortedMapImpl implements MapsImplEnum {
252     TreeMapImpl {
253       @Override
create(Map<K, V> map)254       public <K extends Comparable<K>, V> SortedMap<K, V> create(Map<K, V> map) {
255         SortedMap<K, V> result = Maps.newTreeMap();
256         result.putAll(map);
257         return result;
258       }
259     },
260     ConcurrentSkipListImpl {
261       @Override
create(Map<K, V> map)262       public <K extends Comparable<K>, V> SortedMap<K, V> create(Map<K, V> map) {
263         return new ConcurrentSkipListMap<>(map);
264       }
265     },
266     ImmutableSortedMapImpl {
267       @Override
create(Map<K, V> map)268       public <K extends Comparable<K>, V> SortedMap<K, V> create(Map<K, V> map) {
269         return ImmutableSortedMap.copyOf(map);
270       }
271     };
272   }
273 
274   enum BiMapImpl implements MapsImplEnum {
275     HashBiMapImpl {
276       @Override
create(Map<K, V> map)277       public <K extends Comparable<K>, V> BiMap<K, V> create(Map<K, V> map) {
278         return HashBiMap.create(map);
279       }
280     },
281     ImmutableBiMapImpl {
282       @Override
create(Map<K, V> map)283       public <K extends Comparable<K>, V> BiMap<K, V> create(Map<K, V> map) {
284         return ImmutableBiMap.copyOf(map);
285       }
286     };
287 
288     @Override
create(Map<K, V> map)289     public abstract <K extends Comparable<K>, V> BiMap<K, V> create(Map<K, V> map);
290   }
291 
292   enum MultisetImpl implements CollectionsImplEnum {
293     HashMultisetImpl {
294       @Override
create(Collection<E> contents)295       public <E extends Comparable<E>> Multiset<E> create(Collection<E> contents) {
296         return HashMultiset.create(contents);
297       }
298     },
299     LinkedHashMultisetImpl {
300       @Override
create(Collection<E> contents)301       public <E extends Comparable<E>> Multiset<E> create(Collection<E> contents) {
302         return LinkedHashMultiset.create(contents);
303       }
304     },
305     ConcurrentHashMultisetImpl {
306       @Override
create(Collection<E> contents)307       public <E extends Comparable<E>> Multiset<E> create(Collection<E> contents) {
308         return ConcurrentHashMultiset.create(contents);
309       }
310     },
311     ImmutableMultisetImpl {
312       @Override
create(Collection<E> contents)313       public <E extends Comparable<E>> Multiset<E> create(Collection<E> contents) {
314         return ImmutableMultiset.copyOf(contents);
315       }
316     };
317   }
318 
319   enum SortedMultisetImpl implements CollectionsImplEnum {
320     TreeMultisetImpl {
321       @Override
create(Collection<E> contents)322       public <E extends Comparable<E>> SortedMultiset<E> create(Collection<E> contents) {
323         return TreeMultiset.create(contents);
324       }
325     },
326     ImmutableSortedMultisetImpl {
327       @Override
create(Collection<E> contents)328       public <E extends Comparable<E>> SortedMultiset<E> create(Collection<E> contents) {
329         return ImmutableSortedMultiset.copyOf(contents);
330       }
331     };
332   }
333 
334   enum QueueImpl implements CollectionsImplEnum {
335     MinMaxPriorityQueueImpl {
336       @Override
create(Collection<E> contents)337       public <E extends Comparable<E>> Queue<E> create(Collection<E> contents) {
338         return MinMaxPriorityQueue.create(contents);
339       }
340     };
341   }
342 
343   enum TableImpl {
344     HashBasedTableImpl {
345       @Override
create( Table<R, C, V> contents)346       <R extends Comparable<R>, C extends Comparable<C>, V> Table<R, C, V> create(
347           Table<R, C, V> contents) {
348         return HashBasedTable.create(contents);
349       }
350     },
351     TreeBasedTableImpl {
352       @Override
create( Table<R, C, V> contents)353       <R extends Comparable<R>, C extends Comparable<C>, V> Table<R, C, V> create(
354           Table<R, C, V> contents) {
355         Table<R, C, V> table = TreeBasedTable.create();
356         table.putAll(contents);
357         return table;
358       }
359     },
360     ArrayTableImpl {
361       @Override
create( Table<R, C, V> contents)362       <R extends Comparable<R>, C extends Comparable<C>, V> Table<R, C, V> create(
363           Table<R, C, V> contents) {
364         if (contents.isEmpty()) {
365           return ImmutableTable.of();
366         } else {
367           return ArrayTable.create(contents);
368         }
369       }
370     },
371     ImmutableTableImpl {
372       @Override
create( Table<R, C, V> contents)373       <R extends Comparable<R>, C extends Comparable<C>, V> Table<R, C, V> create(
374           Table<R, C, V> contents) {
375         return ImmutableTable.copyOf(contents);
376       }
377     };
378 
create( Table<R, C, V> contents)379     abstract <R extends Comparable<R>, C extends Comparable<C>, V> Table<R, C, V> create(
380         Table<R, C, V> contents);
381   }
382 
383   public enum InternerImpl implements InternerImplEnum {
384     WeakInternerImpl {
385       @Override
create(Collection<E> contents)386       public <E> Interner<E> create(Collection<E> contents) {
387         Interner<E> interner = Interners.newWeakInterner();
388         for (E e : contents) {
389           interner.intern(e);
390         }
391         return interner;
392       }
393     },
394     StrongInternerImpl {
395       @Override
create(Collection<E> contents)396       public <E> Interner<E> create(Collection<E> contents) {
397         Interner<E> interner = Interners.newStrongInterner();
398         for (E e : contents) {
399           interner.intern(e);
400         }
401         return interner;
402       }
403     };
404   }
405 
406   public enum Value {
407     INSTANCE;
408   }
409 
410   public enum ListSizeDistribution {
411     UNIFORM_0_TO_2(0, 2),
412     UNIFORM_0_TO_9(0, 9),
413     ALWAYS_0(0, 0),
414     ALWAYS_10(10, 10);
415 
416     final int min;
417     final int max;
418 
ListSizeDistribution(int min, int max)419     private ListSizeDistribution(int min, int max) {
420       this.min = min;
421       this.max = max;
422     }
423 
chooseSize(Random random)424     public int chooseSize(Random random) {
425       return random.nextInt(max - min + 1) + min;
426     }
427   }
428 }
429