MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
munmaptest.cpp
1 /*
2  Copyright (C) 2003-2006 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 
20 
21 
22 #include <ndb_global.h>
23 
24 #include <NdbOut.hpp>
25 #include <NdbThread.h>
26 #include <NdbMutex.h>
27 #include <NdbCondition.h>
28 #include <NdbSleep.h>
29 #include <NdbTick.h>
30 #include <NdbEnv.h>
31 #include <NdbHost.h>
32 #include <NdbMain.h>
33 #include <getarg.h>
34 
35 struct ThreadData
36 {
37  char * mapAddr;
38  Uint32 mapSize;
39  Uint32 chunk;
40  Uint32 idx;
41 
42 };
43 
44 long long getMilli();
45 long long getMicro();
46 
47 
48 void* mapSegment(void * arg);
49 void* unmapSegment(void * arg);
50 
51 
52 void* mapSegment(void * arg) {
53 
54  ThreadData * threadArgs;
55  long long start=0;
56  int total=0;
57  int id = *(int *)arg;
58  threadArgs = new ThreadData [1];
59  Uint32 size=5*1024*1024;
60  struct NdbThread* unmapthread_var;
61  void *status = 0;
62  int run = 1;
63  int max=0, min =100000000, sum=0;
64  while(run < 1001) {
65  start=getMicro();
66  char * ptr =(char*) mmap(0,
67  size,
68  PROT_READ|PROT_WRITE,
69  MAP_PRIVATE|MAP_ANONYMOUS,
70  0,
71  0);
72 
73  total=(int)(getMicro()-start);
74 
75  ndbout << "T" << id << ": mmap took : " << total << " microsecs. "
76  << " Run: " << run ;
77  ndbout_c(" mapped @ %p \n", ptr);
78 
79  if(total>max)
80  max = total;
81  if(total<min)
82  min=total;
83 
84  sum+=total;
85 
86  if(ptr<0) {
87  ndbout << "failed to mmap!" << endl;
88  exit(1);
89  }
90 
91 
92  threadArgs[0].mapAddr = (char *)ptr;
93  threadArgs[0].mapSize = size;
94  threadArgs[0].chunk = 4096;
95  threadArgs[0].idx = 0;
96 
97 
98  for(Uint32 j=0; j<size; j=j+4096)
99  ptr[j]='1';
100 
101  unmapthread_var = NdbThread_Create(unmapSegment, // Function
102  (void**)&threadArgs[0],// Arg
103  32768, // Stacksize
104  (char*)"unmapthread", // Thread name
105  NDB_THREAD_PRIO_MEAN); // Thread prio
106 
107 
108  if(NdbThread_WaitFor(unmapthread_var, &status) != 0) {
109  ndbout << "test failed - exitting " << endl;
110  exit(1);
111  }
112  run++;
113  }
114 
115  ndbout << "MAX: " << max << " MIN: " << min;
116  float mean = (float) ((float)sum/(float)run);
117  ndbout_c(" AVERAGE: %2.5f\n",mean);
118 }
119 
120 
121 
122 void* unmapSegment(void * arg)
123 {
124 
125  char * freeAddr;
126  char * mapAddr;
127  ThreadData * threadData = (ThreadData*) arg;
128  int start=0;
129  int total=0;
130  Uint32 mapSize = threadData->mapSize;
131  Uint32 chunk = threadData->chunk;
132  mapAddr = threadData->mapAddr;
133 
134 
135 
136  freeAddr = mapAddr+mapSize-chunk;
137  NdbSleep_MilliSleep(100);
138  for(Uint32 i=0;i<mapSize; i = i+chunk) {
139  start=getMicro();
140  if(munmap(freeAddr, chunk) < 0){
141  ndbout << "munmap failed" << endl;
142  exit(1);
143  }
144  total=(int)(getMicro()-start);
145  freeAddr = freeAddr - chunk;
146  NdbSleep_MilliSleep(10);
147  ndbout << "unmap 4096 bytes : " << total << "microsecs" << endl;
148  }
149  return NULL;
150 }
151 
152 
153 static int trash;
154 static int segmentsize=1;
155 
156 
157 static struct getargs args[] = {
158  { "trash", 't', arg_integer, &trash,
159  "trash the memory before (1 to trash 0 to not trash)", "trash"},
160  { "segment", 's', arg_integer, &segmentsize,
161  "segment size (in MB)", "segment"},
162 };
163 
164 
165 static const int num_args = sizeof(args) / sizeof(args[0]);
166 
167 NDB_MAIN(munmaptest) {
168 
169  const char *progname = "munmaptest";
170  int optind = 0;
171 
172  if(getarg(args, num_args, argc, argv, &optind)) {
173  arg_printusage(args, num_args, progname, "");
174  exit(1);
175  }
176 
177  int size;
178  char * ptr;
179  if(trash) {
180  for(int i=0; i<100; i++) {
181  size=1+(int) (10.0*rand()/(RAND_MAX+1.0));
182  NdbSleep_MilliSleep(10);
183  ptr =(char*) mmap(0,
184  size*1024*1024,
185  PROT_READ|PROT_WRITE,
186  MAP_PRIVATE|MAP_ANONYMOUS,
187  0,
188  0);
189  for(int i=0;i<(size*1024*1024); i=i+4096) {
190  *(ptr+i)='1';
191  }
192  NdbSleep_MilliSleep(10);
193 
194  munmap(ptr,size);
195 
196  }
197 
198 
199  }
200 
201  int noThreads = 1;
202  struct NdbThread* mapthread_var;
203  int id[noThreads];
204  void *status=0;
205 
206  ThreadData * threadArgs = new ThreadData[noThreads];
207 
208 
209 
210 
211  for(int i=0; i < noThreads; i++) {
212  threadArgs[i].mapSize = segmentsize*1024*1024;
213  threadArgs[i].idx = i;
214  mapthread_var = NdbThread_Create(mapSegment, // Function
215  (void**)&threadArgs[i],// Arg
216  32768, // Stacksize
217  (char*)"mapthread", // Thread name
218  NDB_THREAD_PRIO_MEAN); // Thread prio
219 
220  }
221 
222 
223  if(NdbThread_WaitFor(mapthread_var, &status) != 0) {
224  ndbout << "test failed - exitting " << endl;
225  exit(1);
226  }
227 
228 }
229 
230 long long getMilli() {
231  struct timeval tick_time;
232  gettimeofday(&tick_time, 0);
233 
234  return
235  ((long long)tick_time.tv_sec) * ((long long)1000) +
236  ((long long)tick_time.tv_usec) / ((long long)1000);
237 }
238 
239 long long getMicro(){
240  struct timeval tick_time;
241  int res = gettimeofday(&tick_time, 0);
242 
243  long long secs = tick_time.tv_sec;
244  long long micros = tick_time.tv_usec;
245 
246  micros = secs*1000000+micros;
247  return micros;
248 }