diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3902d54cc09..8a78a5a2067 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2004-01-06 Benjamin Kosnik + Stefan Olsson + + * scripts/check_performance: Use -pthread. + * testsuite/performance/allocator.cc: Tweaks, add list. + * testsuite/performance/allocator_thread.cc: New. + 2003-01-06 Jerry Quinn * include/bits/locale_facets.h: Document public classes and diff --git a/libstdc++-v3/scripts/check_performance b/libstdc++-v3/scripts/check_performance index 5fdf5817505..5865114d1eb 100755 --- a/libstdc++-v3/scripts/check_performance +++ b/libstdc++-v3/scripts/check_performance @@ -25,12 +25,13 @@ esac flags_script=$BUILD_DIR/scripts/testsuite_flags INCLUDES=`$flags_script --build-includes` FLAGS=`$flags_script --cxxflags` +THREAD_FLAG='-pthread' COMPILER=`$flags_script --build-cxx` SH_FLAG="-Wl,--rpath -Wl,$BUILD_DIR/../../gcc \ -Wl,--rpath -Wl,$BUILD_DIR/src/.libs" ST_FLAG="-static" LINK=$SH_FLAG -CXX="$COMPILER $INCLUDES $FLAGS $LINK" +CXX="$COMPILER $INCLUDES $FLAGS $THREAD_FLAG $LINK" TESTS_FILE="testsuite_files_performance" diff --git a/libstdc++-v3/testsuite/performance/allocator.cc b/libstdc++-v3/testsuite/performance/allocator.cc index e4a5ad47766..53058edb395 100644 --- a/libstdc++-v3/testsuite/performance/allocator.cc +++ b/libstdc++-v3/testsuite/performance/allocator.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2003 Free Software Foundation, Inc. +// Copyright (C) 2003, 2004 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -26,36 +26,17 @@ // the GNU General Public License. /* - * - * * The goal with this application is to compare the performance - * between different STL allocators relative to the default - * __pool_alloc. - * - * The container used for the tests is vector, which as stated by - * SGI "Vector is the simplest of the STL container classes, and in - * many cases the most efficient.". - * - * NOTE! The vector<> container does some "caching" of it's own and - * therefore we redeclare the variable in each iteration (forcing the - * const/destr to be called and thus free memory). - * - * NOTE! The usage of gettimeofday is unwanted since it's not POSIX, - * however I have not found a more generic system call to use - - * ideas are greatly appriciated! - * - * NOTE! This version only does operations on vector. More/other - * data types should maybe also be tested - ideas are always welcome! - * - * I assume that glibc/underlying malloc() implementation has been - * compiled with -O2 thus should this application also be compiled - * with -O2 in order to get relevant results. + * between different std::allocator implementations. The results are + * influenced by the underlying allocator in the "C" library, malloc. */ // 2003-02-05 Stefan Olsson #include -#include +#include +#include +#include #include #include #include @@ -64,154 +45,97 @@ using namespace std; using __gnu_cxx::malloc_allocator; using __gnu_cxx::__mt_alloc; -/* - * In order to avoid that the time it takes for the application to - * startup/shutdown affect the end result, we define a target - * duration (in seconds) for which all tests should run. - * Each test is responsible for "calibrating" their # of iterations - * to come as close as possible to this target based on the time - * it takes to complete the test using the default __pool_alloc. - */ -int target_run_time = 10; +typedef int test_type; -/* - * The number of iterations to be performed in order to figure out - * the "speed" of this computer and adjust the number of iterations - * needed to come close to target_run_time. - */ -int calibrate_iterations = 100000; +// The number of iterations to be performed. +int iterations; -/* - * The number of values to insert in the vector, 32 will cause - * 5 (re)allocations to be performed (sizes 4, 8, 16, 32 and 64) - * This means that all allocations are within _MAX_BYTES = 128 - * as defined in stl_alloc.h for __pool_alloc. - * Whether or not this value is relevant in "the real world" - * or not I don't know and should probably be investigated in - * more detail. - */ -int insert_values = 32; +// The number of values to insert in the container, 32 will cause 5 +// (re)allocations to be performed (sizes 4, 8, 16, 32 and 64) +// This means that all allocations are within _MAX_BYTES = 128 as +// defined in stl_alloc.h for __pool_alloc. Whether or not this +// value is relevant in "the real world" or not I don't know and +// should probably be investigated in more detail. +int insert_values = 128; -static struct timeval _tstart, _tend; -static struct timezone tz; - -void -tstart(void) -{ - gettimeofday(&_tstart, &tz); -} - -void -tend(void) -{ - gettimeofday(&_tend, &tz); -} - -double -tval() -{ - double t1, t2; - - t1 =(double)_tstart.tv_sec +(double)_tstart.tv_usec/(1000*1000); - t2 =(double)_tend.tv_sec +(double)_tend.tv_usec/(1000*1000); - return t2 - t1; -} - -int -calibrate_test_ints(void) -{ - tstart(); - for (int i = 0; i < calibrate_iterations; i++) +template + int + do_loop() { - vector v1; - - for(int j = 0; j < insert_values; j++) - v1.push_back(1); + int test_iterations = 0; + try + { + Container obj; + while (test_iterations < iterations) + { + for (int j = 0; j < insert_values; ++j) + obj.push_back(test_iterations); + ++test_iterations; + } + } + catch(...) + { + // No point allocating all available memory, repeatedly. + } + return test_iterations; } - tend(); - return(int)((double)target_run_time / tval()) * calibrate_iterations; -} - -double -test_ints_pool_alloc(int iterations) -{ - tstart(); - for(int i = 0; i < iterations; i++) +template + void + calibrate_iterations() { - vector v1; + int try_iterations = iterations = 100000; + int test_iterations; - for(int j = 0; j < insert_values; j++) - v1.push_back(1); + __gnu_test::time_counter timer; + timer.start(); + test_iterations = do_loop(); + timer.stop(); + + if (try_iterations > test_iterations && test_iterations > iterations) + iterations = test_iterations - 100; + else + { + double tics = timer.real_time(); + double iterpc = test_iterations / tics; //iterations per clock + double xtics = 200; // works for linux 2gig x86 + iterations = static_cast(xtics * iterpc); + } } - tend(); - return tval(); -} - -double -test_ints_malloc_alloc(int iterations) -{ - tstart(); - for(int i = 0; i < iterations; i++) +template + void + test_container(Container obj) { - vector > v1; + using namespace __gnu_test; - for(int j = 0; j < insert_values; j++) - { - v1.push_back(1); - } + time_counter time; + resource_counter resource; + clear_counters(time, resource); + start_counters(time, resource); + int test_iterations = do_loop(); + stop_counters(time, resource); + + std::ostringstream comment; + comment << "iterations: " << test_iterations << '\t'; + comment << "type: " << typeid(obj).name(); + report_header(__FILE__, comment.str()); + report_performance(__FILE__, string(), time, resource); } - tend(); - - return tval(); -} - -double -test_ints_mt_alloc(int iterations) -{ - tstart(); - for(int i = 0; i < iterations; i++) - { - vector > v1; - - for(int j = 0; j < insert_values; j++) - { - v1.push_back(1); - } - } - tend(); - - return tval(); -} // http://gcc.gnu.org/ml/libstdc++/2001-05/msg00105.html // http://gcc.gnu.org/ml/libstdc++/2003-05/msg00231.html int main(void) { - using namespace __gnu_test; + calibrate_iterations >(); + test_container(vector()); + test_container(vector >()); + //test_container(vector >()); - time_counter time; - resource_counter resource; - - int iterations = calibrate_test_ints(); - - start_counters(time, resource); - test_ints_pool_alloc(iterations); - stop_counters(time, resource); - report_performance(__FILE__, "default", time, resource); - clear_counters(time, resource); - - start_counters(time, resource); - test_ints_malloc_alloc(iterations); - stop_counters(time, resource); - report_performance(__FILE__, "malloc", time, resource); - clear_counters(time, resource); - - start_counters(time, resource); - test_ints_mt_alloc(iterations); - stop_counters(time, resource); - report_performance(__FILE__, "mt", time, resource); + calibrate_iterations >(); + test_container(list()); + test_container(list >()); + //test_container(list >()); return 0; } diff --git a/libstdc++-v3/testsuite/performance/allocator_thread.cc b/libstdc++-v3/testsuite/performance/allocator_thread.cc new file mode 100644 index 00000000000..016f45a5d30 --- /dev/null +++ b/libstdc++-v3/testsuite/performance/allocator_thread.cc @@ -0,0 +1,154 @@ +// Copyright (C) 2003, 2004 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/* + * The goal with this application is to compare the performance + * between different std::allocator implementations. The results are + * influenced by the underlying allocator in the "C" library, malloc. + */ + +// 2003-02-05 Stefan Olsson + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using __gnu_cxx::malloc_allocator; +using __gnu_cxx::__mt_alloc; + +typedef int test_type; + +// The number of iterations to be performed. +int iterations; + +// The number of values to insert in the container, 32 will cause 5 +// (re)allocations to be performed (sizes 4, 8, 16, 32 and 64) +// This means that all allocations are within _MAX_BYTES = 128 as +// defined in stl_alloc.h for __pool_alloc. Whether or not this +// value is relevant in "the real world" or not I don't know and +// should probably be investigated in more detail. +int insert_values = 128; + +template + void* + do_loop(void* p = NULL) + { + Container obj; + try + { + int test_iterations = 0; + while (test_iterations < iterations) + { + for (int j = 0; j < insert_values; ++j) + obj.push_back(test_iterations); + ++test_iterations; + } + obj.clear(); + test_iterations = 0; + while (test_iterations < iterations) + { + for (int j = 0; j < insert_values; ++j) + obj.push_back(test_iterations); + ++test_iterations; + } + } + catch(...) + { + // No point allocating all available memory, repeatedly. + } + } + +template + void + calibrate_iterations() + { + int try_iterations = iterations = 100000; + + __gnu_test::time_counter timer; + timer.start(); + do_loop(); + timer.stop(); + + double tics = timer.real_time(); + double iterpc = iterations / tics; //iterations per clock + double xtics = 100; // works for linux 2gig x86 + iterations = static_cast(xtics * iterpc); + } + +template + void + test_container(Container obj) + { + using namespace __gnu_test; + time_counter time; + resource_counter resource; + + clear_counters(time, resource); + start_counters(time, resource); + + pthread_t t1, t2, t3, t4; + pthread_create(&t1, 0, &do_loop, 0); + pthread_create(&t2, 0, &do_loop, 0); + pthread_create(&t3, 0, &do_loop, 0); + pthread_create(&t4, 0, &do_loop, 0); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + pthread_join(t3, NULL); + pthread_join(t4, NULL); + + stop_counters(time, resource); + + std::ostringstream comment; + comment << "iterations: " << iterations << '\t'; + comment << "type: " << typeid(obj).name(); + report_header(__FILE__, comment.str()); + report_performance(__FILE__, string(), time, resource); + } + +// http://gcc.gnu.org/ml/libstdc++/2001-05/msg00105.html +// http://gcc.gnu.org/ml/libstdc++/2003-05/msg00231.html +int main(void) +{ + calibrate_iterations >(); + test_container(vector()); + test_container(vector >()); + //test_container(vector >()); + + calibrate_iterations >(); + test_container(list()); + test_container(list >()); + //test_container(list >()); + + return 0; +}