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 48static int result = 0; 49static int g_iters = 0; // argv[1] 50 51Mutex mutex(Mutex::LINKER_INITIALIZED); 52 53static 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 69static 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 81int 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