[llvm-commits] [test-suite] r49140 - /test-suite/trunk/SingleSource/Benchmarks/Misc-C++/stepanov_container.cpp

Owen Anderson resistor at mac.com
Wed Apr 2 22:28:40 PDT 2008


Author: resistor
Date: Thu Apr  3 00:28:40 2008
New Revision: 49140

URL: http://llvm.org/viewvc/llvm-project?rev=49140&view=rev
Log:
Add Stepanov's benchmark of STL container performance.

Added:
    test-suite/trunk/SingleSource/Benchmarks/Misc-C++/stepanov_container.cpp

Added: test-suite/trunk/SingleSource/Benchmarks/Misc-C++/stepanov_container.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/SingleSource/Benchmarks/Misc-C%2B%2B/stepanov_container.cpp?rev=49140&view=auto

==============================================================================
--- test-suite/trunk/SingleSource/Benchmarks/Misc-C++/stepanov_container.cpp (added)
+++ test-suite/trunk/SingleSource/Benchmarks/Misc-C++/stepanov_container.cpp Thu Apr  3 00:28:40 2008
@@ -0,0 +1,259 @@
+/* Standard Container Benchmark 
+
+
+   Version 0.9, May 23, 2003 
+
+
+The primary purpose of this benchmark is to show how different standard 
+containers are in terms of performance. We have observed that programmers 
+often use sets, multisets, deques in the situations where sorted vectors 
+are the optimal solutions. Similarly, programmers often choose lists simply 
+because they do a few insertions and deletions without knowing that vectors 
+are more efficient at that for small containers. 
+
+
+Frequently, of course, performance does not matter, 
+but it is important that programmers are aware of the consequences of their 
+choices. We are not saying that only vectors should be used, there are 
+cases when one really needs a more complicated data structure, but one needs to 
+understand the price for additional functionality. 
+
+
+The secondary purpose of the benchmark is to encourage compiler and library vendors to 
+keep improving performance. For example, it is not acceptable that some compilers give 
+you a sizable penalty for using vector iterators instead of pointer. It is also quite 
+clear that  performance of other standard containers could be improved. 
+
+
+The benchmark is doing the same task 7 times using different data structures: 
+array, vector (using a pointer as iterator), vector (using the defailt cector iterator), 
+list, deque, set and multiset. The task is to remove duplicates from a sequence of doubles. 
+This is a simple test, but it illustrates the performance of containers. 
+
+
+It is clear that the benchmark needs to be eventually extended 
+to slists and even to hash-sets and hash-maps, but we decided that at present it 
+should work only with the standard containers. As the standard grows, so can 
+the benchmark. The additional benefit of not including hash based containers is 
+that now all the test have identical asymptotic complexity and, even more 
+importantly, do almost the same number of comparisons. The difference is only 
+in data structure overhead and cache behavior. 
+
+
+The number of times that a given test is run inversly proportional to NlogN where N is the 
+size of the sequence.  This allows one to see how containers of different size behave. 
+The instructive values used for the benchmark are: 10, 100, 1000, 10000, 100000, 1000000. 
+
+
+The time taken for a run of the benchmark depends on the machine used, the compiler used, 
+the compiler and optimizer settings used, as well as the standard library. Please note that 
+the time taken could be several minutes - and much more if you use a slow debug mode. 
+
+
+The output is a table where columns are separated by tabs and rows by newlines. This is 
+barely ok for a human reader, but ideal for feeding into a program, such as a spreadsheet 
+for display or analysis. 
+
+
+If you want to add your own test of a container, add the name of your container to 
+the "header string, write a test function like the existing ones, e.g. vector_test, 
+and add a call of "run" for your test in "run_tests". 
+
+
+Alex Stepanov 
+stepa... at adobe.com 
+
+
+Bjarne Stroustrup 
+b... at cs.tamu.edu 
+
+
+*/ 
+
+
+#include <stddef.h>       // some older implementations lack <cstddef> 
+#include <time.h> 
+#include <math.h> 
+#include <stdlib.h> 
+
+
+#include <vector> 
+#include <algorithm> 
+#include <list> 
+#include <deque> 
+#include <set> 
+
+
+#include <iostream> 
+#include <iomanip> 
+
+
+typedef double element_t; 
+
+
+using namespace std; 
+
+
+vector<double> result_times; // results are puched into this vector 
+
+
+typedef void(*Test)(element_t*, element_t*, int); 
+void run(Test f, element_t* first, element_t* last, int number_of_times) 
+{ 
+        while (number_of_times-- > 0) f(first,last,number_of_times); 
+} 
+
+
+void array_test(element_t* first, element_t* last, int number_of_times) 
+{ 
+       element_t* array = new element_t[last - first]; 
+       copy(first, last, array); 
+       sort(array, array + (last - first)); 
+       unique(array, array + (last - first)); 
+       delete [] array;   
+
+
+} 
+
+
+void vector_pointer_test(element_t* first, element_t* last, int number_of_times) 
+{ 
+       vector<element_t> container(first, last); 
+           // &*container.begin() gets us a pointer to the first element 
+       sort(&*container.begin(), &*container.end()); 
+       unique(&*container.begin(), &*container.end()); 
+
+
+} 
+
+
+void vector_iterator_test(element_t* first, element_t* last, int number_of_times) 
+{ 
+       vector<element_t> container(first, last); 
+       sort(container.begin(), container.end()); 
+       unique(container.begin(), container.end()); 
+
+
+} 
+
+
+void deque_test(element_t* first, element_t* last, int number_of_times) 
+{   
+//       deque<element_t> container(first, last); CANNOT BE USED BECAUSE OF MVC++ 6 
+        deque<element_t> container(size_t(last - first), 0.0); 
+        copy(first, last, container.begin()); 
+        sort(container.begin(), container.end()); 
+        unique(container.begin(), container.end()); 
+
+
+} 
+
+
+void list_test(element_t* first, element_t* last, int number_of_times) 
+{ 
+       list<element_t> container(first, last); 
+       container.sort(); 
+           container.unique(); 
+
+
+} 
+
+
+void set_test(element_t* first, element_t* last, int number_of_times) 
+{ 
+       set<element_t> container(first, last); 
+
+
+} 
+
+
+void multiset_test(element_t* first, element_t* last, int number_of_times) 
+{ 
+       multiset<element_t> container(first, last); 
+       typedef multiset<element_t>::iterator iterator; 
+           { 
+                        iterator first = container.begin(); 
+                        iterator last = container.end(); 
+
+                        while (first != last) { 
+                                iterator next = first; 
+                                if (++next == last) break; 
+                                if (*first == *next) 
+                                        container.erase(next); 
+                                else 
+                                        ++first; 
+                        } 
+           } 
+
+
+
+} 
+
+
+void initialize(element_t* first, element_t* last) 
+{ 
+  element_t value = 0.0; 
+  while (first != last) { 
+         *first++ = value; 
+         value += 1.; 
+  } 
+
+
+} 
+
+
+double logtwo(double x) 
+{ 
+  return log(x)/log((double) 2.0); 
+
+
+} 
+
+
+const int largest_size = 1000000; 
+
+int number_of_tests(int size) { 
+        double n = size; 
+        double largest_n = largest_size; 
+        return int(floor((largest_n * logtwo(largest_n)) / (n * logtwo(n)))); 
+
+
+
+} 
+
+
+void run_tests(int size) 
+{ 
+        const int n = number_of_tests(size); 
+        const size_t length = 2*size; 
+        result_times.clear(); 
+
+// make a random test set of the chosen size: 
+  vector<element_t> buf(length); 
+  element_t* buffer = &buf[0]; 
+  element_t* buffer_end = &buf[length]; 
+  initialize(buffer, buffer + size);            // elements 
+  initialize(buffer + size, buffer_end);        // duplicate elements 
+  random_shuffle(buffer, buffer_end); 
+
+
+// test the containers: 
+  run(array_test, buffer, buffer_end, n); 
+  run(vector_pointer_test, buffer, buffer_end, n); 
+  run(vector_iterator_test, buffer, buffer_end, n); 
+  run(deque_test, buffer, buffer_end, n); 
+  run(list_test, buffer, buffer_end, n); 
+  run(set_test, buffer, buffer_end, n); 
+  run(multiset_test, buffer, buffer_end, n); 
+
+
+
+} 
+
+
+int main() 
+{ 
+  const int sizes [] = { 100000 }; 
+  const int n = sizeof(sizes)/sizeof(int); 
+  for (int i = 0; i < n; ++i) run_tests(sizes[i]);
+}
\ No newline at end of file





More information about the llvm-commits mailing list