VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTMemCache.cpp@ 26517

Last change on this file since 26517 was 26484, checked in by vboxsync, 15 years ago

blank lines.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.4 KB
Line 
1/* $Id: tstRTMemCache.cpp 26484 2010-02-14 02:15:03Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTMemCache.
4 */
5
6/*
7 * Copyright (C) 2010 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31/*******************************************************************************
32* Header Files *
33*******************************************************************************/
34#include <iprt/memcache.h>
35
36#include <iprt/asm.h>
37#include <iprt/err.h>
38#include <iprt/cache.h>
39#include <iprt/initterm.h>
40#include <iprt/mem.h>
41#include <iprt/param.h>
42#include <iprt/rand.h>
43#include <iprt/string.h>
44#include <iprt/semaphore.h>
45#include <iprt/test.h>
46#include <iprt/time.h>
47#include <iprt/thread.h>
48
49
50/*******************************************************************************
51* Structures and Typedefs *
52*******************************************************************************/
53typedef struct TST3THREAD
54{
55 RTTHREAD hThread;
56 RTSEMEVENTMULTI hEvt;
57 uint64_t volatile cIterations;
58 uint32_t cbObject;
59 bool fUseCache;
60 bool fUseOldCache;
61} TST3THREAD, *PTST3THREAD;
62
63
64/*******************************************************************************
65* Global Variables *
66*******************************************************************************/
67/** The test handle */
68static RTTEST g_hTest;
69/** Global mem cache handle for use in some of the testcases. */
70static RTMEMCACHE g_hMemCache;
71/** For testcase 3. */
72static PRTOBJCACHE g_pOldCacheTst3;
73/** Stop indicator for tst3 threads. */
74static bool volatile g_fTst3Stop;
75
76
77/**
78 * Basic API checks.
79 * We'll return if any of these fails.
80 */
81static void tst1(void)
82{
83 RTTestISub("Basics");
84
85 /* Create one without constructor or destructor. */
86 uint32_t const cObjects = PAGE_SIZE * 2 / 256;
87 RTMEMCACHE hMemCache;
88 RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&hMemCache, 256, cObjects, 32, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS);
89 RTTESTI_CHECK_RETV(hMemCache != NIL_RTMEMCACHE);
90
91 /* Allocate a bit and free it again. */
92 void *pv = NULL;
93 RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(hMemCache, &pv), VINF_SUCCESS);
94 RTTESTI_CHECK_RETV(pv != NULL);
95 RTTESTI_CHECK_RETV(RT_ALIGN_P(pv, 32) == pv);
96 RTMemCacheFree(hMemCache, pv);
97
98 RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) != NULL);
99 RTMemCacheFree(hMemCache, pv);
100
101 /* Allocate everything and free it again, checking size constraints. */
102 for (uint32_t iLoop = 0; iLoop < 20; iLoop++)
103 {
104 /* Allocate everything. */
105 void *apv[cObjects];
106 for (uint32_t i = 0; i < cObjects; i++)
107 {
108 apv[i] = NULL;
109 RTTESTI_CHECK_RC(RTMemCacheAllocEx(hMemCache, &apv[i]), VINF_SUCCESS);
110 }
111
112 /* Check that we've got it all. */
113 int rc;
114 RTTESTI_CHECK_RC(rc = RTMemCacheAllocEx(hMemCache, &pv), VERR_MEM_CACHE_MAX_SIZE);
115 if (RT_SUCCESS(rc))
116 RTMemCacheFree(hMemCache, pv);
117
118 RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) == NULL);
119 RTMemCacheFree(hMemCache, pv);
120
121 /* Free all the allocations. */
122 for (uint32_t i = 0; i < cObjects; i++)
123 {
124 RTMemCacheFree(hMemCache, apv[i]);
125
126 RTTESTI_CHECK((pv = RTMemCacheAlloc(hMemCache)) != NULL);
127 RTMemCacheFree(hMemCache, pv);
128 }
129 }
130
131 /* Destroy it. */
132 RTTESTI_CHECK_RC(RTMemCacheDestroy(hMemCache), VINF_SUCCESS);
133 RTTESTI_CHECK_RC(RTMemCacheDestroy(NIL_RTMEMCACHE), VINF_SUCCESS);
134}
135
136
137
138/** Constructor for tst2. */
139static DECLCALLBACK(int) tst2Ctor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
140{
141 RTTESTI_CHECK(hMemCache == g_hMemCache);
142 RTTESTI_CHECK(ASMMemIsAll8(pvObj, 256, 0) == NULL);
143
144 if (*(bool *)pvUser)
145 return VERR_RESOURCE_BUSY;
146
147 strcat((char *)pvObj, "ctor was called\n");
148 return VINF_SUCCESS;
149}
150
151
152/** Destructor for tst2. Checks that it was constructed and used twice. */
153static DECLCALLBACK(void) tst2Dtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
154{
155 RTTESTI_CHECK(!strcmp((char *)pvObj, "ctor was called\nused\nused\n"));
156 strcat((char *)pvObj, "dtor was called\n");
157}
158
159/**
160 * Test constructor / destructor.
161 */
162static void tst2(void)
163{
164 RTTestISub("Ctor/Dtor");
165
166 /* Create one without constructor or destructor. */
167 bool fFail = false;
168 uint32_t const cObjects = PAGE_SIZE * 2 / 256;
169 RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, 256, cObjects, 32, tst2Ctor, tst2Dtor, &fFail, 0 /*fFlags*/), VINF_SUCCESS);
170
171 /* A failure run first. */
172 fFail = true;
173 void *pv = (void *)0x42;
174 RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(g_hMemCache, &pv), VERR_RESOURCE_BUSY);
175 RTTESTI_CHECK(pv == (void *)0x42);
176 fFail = false;
177
178 /* To two rounds where we allocate all the objects and free them again. */
179 for (uint32_t iLoop = 0; iLoop < 2; iLoop++)
180 {
181 void *apv[cObjects];
182 for (uint32_t i = 0; i < cObjects; i++)
183 {
184 apv[i] = NULL;
185 RTTESTI_CHECK_RC_RETV(RTMemCacheAllocEx(g_hMemCache, &apv[i]), VINF_SUCCESS);
186 if (iLoop == 0)
187 RTTESTI_CHECK(!strcmp((char *)apv[i], "ctor was called\n"));
188 else
189 RTTESTI_CHECK(!strcmp((char *)apv[i], "ctor was called\nused\n"));
190 strcat((char *)apv[i], "used\n");
191 }
192
193 RTTESTI_CHECK_RETV((pv = RTMemCacheAlloc(g_hMemCache)) == NULL);
194 RTMemCacheFree(g_hMemCache, pv);
195
196 for (uint32_t i = 0; i < cObjects; i++)
197 RTMemCacheFree(g_hMemCache, apv[i]);
198 }
199
200 /* Cone, destroy the cache. */
201 RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS);
202}
203
204
205/**
206 * Thread that allocates
207 * @returns
208 * @param hThreadSelf The thread.
209 * @param pvArg Pointer to fUseCache.
210 */
211static DECLCALLBACK(int) tst3Thread(RTTHREAD hThreadSelf, void *pvArg)
212{
213 PTST3THREAD pThread = (PTST3THREAD)(pvArg);
214 size_t cbObject = pThread->cbObject;
215 uint64_t cIterations = 0;
216
217 /* wait for the kick-off */
218 RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(pThread->hEvt, RT_INDEFINITE_WAIT));
219
220 /* allocate and free loop */
221 if (pThread->fUseCache)
222 {
223 while (!g_fTst3Stop)
224 {
225 void *apv[64];
226 for (unsigned i = 0; i < RT_ELEMENTS(apv); i++)
227 {
228 apv[i] = RTMemCacheAlloc(g_hMemCache);
229 RTTEST_CHECK(g_hTest, apv[i] != NULL);
230 }
231 for (unsigned i = 0; i < RT_ELEMENTS(apv); i++)
232 RTMemCacheFree(g_hMemCache, apv[i]);
233
234 cIterations += RT_ELEMENTS(apv);
235 }
236 }
237 else if (pThread->fUseOldCache)
238 {
239 while (!g_fTst3Stop)
240 {
241 void *apv[64];
242
243 for (unsigned i = 0; i < RT_ELEMENTS(apv); i++)
244 {
245 apv[i] = NULL;
246 RTTEST_CHECK_RC_OK(g_hTest, RTCacheRequest(g_pOldCacheTst3, &apv[i]));
247 }
248
249 for (unsigned i = 0; i < RT_ELEMENTS(apv); i++)
250 RTCacheInsert(g_pOldCacheTst3, apv[i]);
251
252 cIterations += RT_ELEMENTS(apv);
253 }
254 }
255 else
256 {
257 while (!g_fTst3Stop)
258 {
259 void *apv[64];
260
261 for (unsigned i = 0; i < RT_ELEMENTS(apv); i++)
262 {
263 apv[i] = RTMemAlloc(cbObject);
264 RTTEST_CHECK(g_hTest, apv[i] != NULL);
265 }
266
267 for (unsigned i = 0; i < RT_ELEMENTS(apv); i++)
268 RTMemFree(apv[i]);
269
270 cIterations += RT_ELEMENTS(apv);
271 }
272 }
273
274 /* report back the status */
275 pThread->cIterations = cIterations;
276 return VINF_SUCCESS;
277}
278
279/**
280 * Time constrained test with and unlimited N threads.
281 */
282static void tst3(uint32_t cThreads, uint32_t cbObject, int iMethod, uint32_t cSecs)
283{
284 RTTestISubF("Benchmark - %u threads, %u bytes, %u secs, %s", cThreads, cbObject, cSecs,
285 iMethod == 0 ? "RTMemCache"
286 : iMethod == 1 ? "RTCache"
287 : "RTMemAlloc");
288
289 /*
290 * Create a cache with unlimited space, a start semaphore and line up
291 * the threads.
292 */
293 RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, cbObject, 0 /*cbAlignment*/, UINT32_MAX, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS);
294 RTTESTI_CHECK_RC_RETV(RTCacheCreate(&g_pOldCacheTst3, 0, cbObject, RTOBJCACHE_PROTECT_INSERT | RTOBJCACHE_PROTECT_REQUEST), VINF_SUCCESS);
295
296 RTSEMEVENTMULTI hEvt;
297 RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiCreate(&hEvt));
298
299 TST3THREAD aThreads[64];
300 RTTESTI_CHECK_RETV(cThreads < RT_ELEMENTS(aThreads));
301
302 ASMAtomicWriteBool(&g_fTst3Stop, false);
303 for (uint32_t i = 0; i < cThreads; i++)
304 {
305 aThreads[i].hThread = NIL_RTTHREAD;
306 aThreads[i].cIterations = 0;
307 aThreads[i].fUseCache = iMethod == 0;
308 aThreads[i].fUseOldCache= iMethod == 1;
309 aThreads[i].cbObject = cbObject;
310 aThreads[i].hEvt = hEvt;
311 RTTESTI_CHECK_RC_OK_RETV(RTThreadCreateF(&aThreads[i].hThread, tst3Thread, &aThreads[i], 0,
312 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst3-%u", i));
313 }
314
315 /*
316 * Start the race.
317 */
318 RTTimeNanoTS(); /* warmup */
319
320 uint64_t uStartTS = RTTimeNanoTS();
321 RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiSignal(hEvt));
322 RTThreadSleep(cSecs * 1000);
323 ASMAtomicWriteBool(&g_fTst3Stop, true);
324 for (uint32_t i = 0; i < cThreads; i++)
325 RTTESTI_CHECK_RC_OK_RETV(RTThreadWait(aThreads[i].hThread, 60*1000, NULL));
326 uint64_t cElapsedNS = RTTimeNanoTS() - uStartTS;
327
328 /*
329 * Sum up the counts.
330 */
331 uint64_t cIterations = 0;
332 for (uint32_t i = 0; i < cThreads; i++)
333 cIterations += aThreads[i].cIterations;
334
335 RTTestIPrintf(RTTESTLVL_ALWAYS, "%'8u iterations per second, %'llu ns on avg\n",
336 (unsigned)((long double)cIterations * 1000000000.0 / cElapsedNS),
337 cElapsedNS / cIterations);
338
339 /* clean up */
340 RTTESTI_CHECK_RC(RTCacheDestroy(g_pOldCacheTst3), VINF_SUCCESS);
341 RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS);
342 RTTESTI_CHECK_RC_OK(RTSemEventMultiDestroy(hEvt));
343}
344
345static void tst3AllMethods(uint32_t cThreads, uint32_t cbObject, uint32_t cSecs)
346{
347 tst3(cThreads, cbObject, 0, cSecs);
348 tst3(cThreads, cbObject, 1, cSecs);
349 tst3(cThreads, cbObject, 2, cSecs);
350}
351
352
353int main(int argc, char **argv)
354{
355 RTTEST hTest;
356 int rc = RTTestInitAndCreate("tstRTMemCache", &hTest);
357 if (rc)
358 return rc;
359 RTTestBanner(hTest);
360 g_hTest = hTest;
361
362 tst1();
363 tst2();
364 if (RTTestIErrorCount() == 0)
365 {
366 uint32_t cSecs = argc == 1 ? 5 : 2;
367 /* threads, cbObj, cSecs */
368 tst3AllMethods( 1, 256, cSecs);
369 tst3AllMethods( 1, 32, cSecs);
370 tst3AllMethods( 1, 8, cSecs);
371 tst3AllMethods( 1, 2, cSecs);
372 tst3AllMethods( 1, 1, cSecs);
373
374 tst3AllMethods( 3, 256, cSecs);
375 tst3AllMethods( 3, 128, cSecs);
376 tst3AllMethods( 3, 64, cSecs);
377 tst3AllMethods( 3, 32, cSecs);
378 tst3AllMethods( 3, 2, cSecs);
379 tst3AllMethods( 3, 1, cSecs);
380
381 tst3AllMethods( 16, 32, cSecs);
382 }
383
384 /*
385 * Summary.
386 */
387 return RTTestSummaryAndDestroy(hTest);
388}
389
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette