// Copyright (c) 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // --- // Author: Craig Silverstein // // Does some simple arithmetic and a few libc routines, so we can profile it. // Define WITH_THREADS to add pthread functionality as well (otherwise, btw, // the num_threads argument to this program is ingored). #include "config_for_unittests.h" #include <stdio.h> #include <stdlib.h> #ifdef HAVE_UNISTD_H #include <unistd.h> // for fork() #endif #include <sys/wait.h> // for wait() #include "gperftools/profiler.h" #include "base/simple_mutex.h" #include "tests/testutil.h" static int result = 0; static int g_iters = 0; // argv[1] Mutex mutex(Mutex::LINKER_INITIALIZED); static void test_other_thread() { #ifndef NO_THREADS ProfilerRegisterThread(); int i, m; char b[128]; MutexLock ml(&mutex); for (m = 0; m < 1000000; ++m) { // run millions of times for (i = 0; i < g_iters; ++i ) { result ^= i; } snprintf(b, sizeof(b), "other: %d", result); // get some libc action } #endif } static void test_main_thread() { int i, m; char b[128]; MutexLock ml(&mutex); for (m = 0; m < 1000000; ++m) { // run millions of times for (i = 0; i < g_iters; ++i ) { result ^= i; } snprintf(b, sizeof(b), "same: %d", result); // get some libc action } } int main(int argc, char** argv) { if ( argc <= 1 ) { fprintf(stderr, "USAGE: %s <iters> [num_threads] [filename]\n", argv[0]); fprintf(stderr, " iters: How many million times to run the XOR test.\n"); fprintf(stderr, " num_threads: how many concurrent threads.\n"); fprintf(stderr, " 0 or 1 for single-threaded mode,\n"); fprintf(stderr, " -# to fork instead of thread.\n"); fprintf(stderr, " filename: The name of the output profile.\n"); fprintf(stderr, (" If you don't specify, set CPUPROFILE " "in the environment instead!\n")); return 1; } g_iters = atoi(argv[1]); int num_threads = 1; const char* filename = NULL; if (argc > 2) { num_threads = atoi(argv[2]); } if (argc > 3) { filename = argv[3]; } if (filename) { ProfilerStart(filename); } test_main_thread(); ProfilerFlush(); // just because we can // The other threads, if any, will run only half as long as the main thread RunManyThreads(test_other_thread, num_threads); // Or maybe they asked to fork. The fork test is only interesting // when we use CPUPROFILE to name, so check for that #ifdef HAVE_UNISTD_H for (; num_threads < 0; ++num_threads) { // -<num_threads> to fork if (filename) { printf("FORK test only makes sense when no filename is specified.\n"); return 2; } switch (fork()) { case -1: printf("FORK failed!\n"); return 1; case 0: // child return execl(argv[0], argv[0], argv[1], NULL); default: wait(NULL); // we'll let the kids run one at a time } } #endif test_main_thread(); if (filename) { ProfilerStop(); } return 0; }