1 // Copyright (c) 2005, Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // --- 31 // Author: Craig Silverstein 32 // 33 // Does some simple arithmetic and a few libc routines, so we can profile it. 34 // Define WITH_THREADS to add pthread functionality as well (otherwise, btw, 35 // the num_threads argument to this program is ingored). 36 37 #include "config_for_unittests.h" 38 #include <stdio.h> 39 #include <stdlib.h> 40 #ifdef HAVE_UNISTD_H 41 #include <unistd.h> // for fork() 42 #endif 43 #include <sys/wait.h> // for wait() 44 #include "gperftools/profiler.h" 45 #include "base/simple_mutex.h" 46 #include "tests/testutil.h" 47 48 static int result = 0; 49 static int g_iters = 0; // argv[1] 50 51 Mutex mutex(Mutex::LINKER_INITIALIZED); 52 53 static void test_other_thread() { 54 #ifndef NO_THREADS 55 ProfilerRegisterThread(); 56 57 int i, m; 58 char b[128]; 59 MutexLock ml(&mutex); 60 for (m = 0; m < 1000000; ++m) { // run millions of times 61 for (i = 0; i < g_iters; ++i ) { 62 result ^= i; 63 } 64 snprintf(b, sizeof(b), "other: %d", result); // get some libc action 65 } 66 #endif 67 } 68 69 static void test_main_thread() { 70 int i, m; 71 char b[128]; 72 MutexLock ml(&mutex); 73 for (m = 0; m < 1000000; ++m) { // run millions of times 74 for (i = 0; i < g_iters; ++i ) { 75 result ^= i; 76 } 77 snprintf(b, sizeof(b), "same: %d", result); // get some libc action 78 } 79 } 80 81 int main(int argc, char** argv) { 82 if ( argc <= 1 ) { 83 fprintf(stderr, "USAGE: %s <iters> [num_threads] [filename]\n", argv[0]); 84 fprintf(stderr, " iters: How many million times to run the XOR test.\n"); 85 fprintf(stderr, " num_threads: how many concurrent threads.\n"); 86 fprintf(stderr, " 0 or 1 for single-threaded mode,\n"); 87 fprintf(stderr, " -# to fork instead of thread.\n"); 88 fprintf(stderr, " filename: The name of the output profile.\n"); 89 fprintf(stderr, (" If you don't specify, set CPUPROFILE " 90 "in the environment instead!\n")); 91 return 1; 92 } 93 94 g_iters = atoi(argv[1]); 95 int num_threads = 1; 96 const char* filename = NULL; 97 if (argc > 2) { 98 num_threads = atoi(argv[2]); 99 } 100 if (argc > 3) { 101 filename = argv[3]; 102 } 103 104 if (filename) { 105 ProfilerStart(filename); 106 } 107 108 test_main_thread(); 109 110 ProfilerFlush(); // just because we can 111 112 // The other threads, if any, will run only half as long as the main thread 113 RunManyThreads(test_other_thread, num_threads); 114 115 // Or maybe they asked to fork. The fork test is only interesting 116 // when we use CPUPROFILE to name, so check for that 117 #ifdef HAVE_UNISTD_H 118 for (; num_threads < 0; ++num_threads) { // -<num_threads> to fork 119 if (filename) { 120 printf("FORK test only makes sense when no filename is specified.\n"); 121 return 2; 122 } 123 switch (fork()) { 124 case -1: 125 printf("FORK failed!\n"); 126 return 1; 127 case 0: // child 128 return execl(argv[0], argv[0], argv[1], NULL); 129 default: 130 wait(NULL); // we'll let the kids run one at a time 131 } 132 } 133 #endif 134 135 test_main_thread(); 136 137 if (filename) { 138 ProfilerStop(); 139 } 140 141 return 0; 142 } 143