/** * Do-once callback that initializes the read/write semaphore and registers * the built-in interpreters. * * @returns IPRT status code. * @param pvUser1 NULL. * @param pvUser2 NULL. */ static DECLCALLBACK(int) rtDbgModInitOnce(void *pvUser1, void *pvUser2) { /* * Create the semaphore and string cache. */ int rc = RTSemRWCreate(&g_hDbgModRWSem); AssertRCReturn(rc, rc); rc = RTStrCacheCreate(&g_hDbgModStrCache, "RTDBGMOD"); if (RT_SUCCESS(rc)) { /* * Register the interpreters. */ rc = rtDbgModDebugInterpreterRegister(&g_rtDbgModVtDbgNm); if (RT_SUCCESS(rc)) { /* * Finally, register the IPRT cleanup callback. */ rc = RTTermRegisterCallback(rtDbgModTermCallback, NULL); if (RT_SUCCESS(rc)) return VINF_SUCCESS; /* bail out: use the termination callback. */ } } else g_hDbgModStrCache = NIL_RTSTRCACHE; rtDbgModTermCallback(RTTERMREASON_UNLOAD, 0, NULL); return rc; }
/** * Check hash and memory performance. */ static void tst2(void) { RTTestISub("Hash performance"); /* * Generate test strings using a specific pseudo random generator. */ size_t cbStrings = 0; char *apszTests[8192]; RTRAND hRand; RTTESTI_CHECK_RC_RETV(RTRandAdvCreateParkMiller(&hRand), VINF_SUCCESS); for (uint32_t i = 0; i < 8192; i++) { char szBuf[8192]; uint32_t cch = RTRandAdvU32Ex(hRand, 3, sizeof(szBuf) - 1); RTRandAdvBytes(hRand, szBuf, cch); szBuf[cch] = '\0'; for (uint32_t off = 0; off < cch; off++) { uint8_t b = szBuf[off]; b &= 0x7f; if (!b || b == 0x7f) b = ' '; else if (RTLocCIsCntrl(b) && b != '\n' && b != '\r' && b != '\t') b += 0x30; szBuf[off] = b; } apszTests[i] = (char *)RTMemDup(szBuf, cch + 1); RTTESTI_CHECK_RETV(apszTests[i] != NULL); cbStrings += cch + 1; } RTRandAdvDestroy(hRand); RTTestIValue("Average string", cbStrings / RT_ELEMENTS(apszTests), RTTESTUNIT_BYTES); /* * Test new insertion first time around. */ RTSTRCACHE hStrCache; RTTESTI_CHECK_RC_RETV(RTStrCacheCreate(&hStrCache, "hash performance"), VINF_SUCCESS); uint64_t nsTsStart = RTTimeNanoTS(); for (uint32_t i = 0; i < RT_ELEMENTS(apszTests); i++) RTTESTI_CHECK_RETV(RTStrCacheEnter(hStrCache, apszTests[i]) != NULL); uint64_t cNsElapsed = RTTimeNanoTS() - nsTsStart; RTTestIValue("First insert", cNsElapsed / RT_ELEMENTS(apszTests), RTTESTUNIT_NS_PER_CALL); /* * Insert existing strings. */ nsTsStart = RTTimeNanoTS(); for (uint32_t i = 0; i < 8192; i++) RTTESTI_CHECK(RTStrCacheEnter(hStrCache, apszTests[i]) != NULL); cNsElapsed = RTTimeNanoTS() - nsTsStart; RTTestIValue("Duplicate insert", cNsElapsed / RT_ELEMENTS(apszTests), RTTESTUNIT_NS_PER_CALL); tstShowStats(hStrCache); RTTESTI_CHECK_RC(RTStrCacheDestroy(hStrCache), VINF_SUCCESS); }
int main() { RTTEST hTest; int rc = RTTestInitAndCreate("tstRTStrCache", &hTest); if (rc) return rc; RTTestBanner(hTest); /* * Smoke tests using first the default and then a custom pool. */ RTTestSub(hTest, "Smoke test on default cache"); tst1(RTSTRCACHE_DEFAULT); RTTestSub(hTest, "Smoke test on custom cache"); RTSTRCACHE hStrCache; RTTESTI_CHECK_RC(rc = RTStrCacheCreate(&hStrCache, "test 2a"), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(rc = RTStrCacheDestroy(hStrCache), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTStrCacheDestroy(NIL_RTSTRCACHE), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTStrCacheDestroy(RTSTRCACHE_DEFAULT), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTStrCacheDestroy(RTSTRCACHE_DEFAULT), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTStrCacheCreate(&hStrCache, "test 2b"), VINF_SUCCESS); if (RT_SUCCESS(rc)) { tst1(hStrCache); RTTESTI_CHECK_RC(rc = RTStrCacheDestroy(hStrCache), VINF_SUCCESS); } /* * Cache performance on relatively real world examples. */ tst2(); /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }