#include #include #include #include #include "taosmsg.h" #include "tskiplist.h" #include "ttime.h" #include "tutil.h" namespace { char* getkey(const void* data) { return (char*)(data); } void doubleSkipListTest() { SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_DOUBLE, sizeof(double), 0, false, true, getkey); double doubleVal[1000] = {0}; int32_t size = 20000; printf("generated %d keys is: \n", size); for (int32_t i = 0; i < size; ++i) { if (i < 1000) { doubleVal[i] = i * 0.997; } int32_t level = 0; int32_t size = 0; tSkipListRandNodeInfo(pSkipList, &level, &size); auto d = (SSkipListNode*)calloc(1, size + sizeof(double) * 2); d->level = level; double* key = (double*)SL_GET_NODE_KEY(pSkipList, d); key[0] = i * 0.997; key[1] = i * 0.997; tSkipListPut(pSkipList, d); } printf("the first level of skip list is:\n"); tSkipListPrint(pSkipList, 1); #if 0 SSkipListNode **pNodes = NULL; SSkipListKey sk; for (int32_t i = 0; i < 100; ++i) { sk.nType = TSDB_DATA_TYPE_DOUBLE; int32_t idx = abs((i * rand()) % 1000); sk.dKey = doubleVal[idx]; int32_t size = tSkipListGets(pSkipList, &sk, &pNodes); printf("the query result size is: %d\n", size); for (int32_t j = 0; j < size; ++j) { printf("the result is: %lf\n", pNodes[j]->key.dKey); } if (size > 0) { tfree(pNodes); } } #endif printf("double test end...\n"); tSkipListDestroy(pSkipList); } void randKeyTest() { SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_INT, sizeof(int32_t), 0, false, true, getkey); int32_t size = 200000; srand(time(NULL)); printf("generated %d keys is: \n", size); for (int32_t i = 0; i < size; ++i) { int32_t level = 0; int32_t s = 0; tSkipListRandNodeInfo(pSkipList, &level, &s); auto d = (SSkipListNode*)calloc(1, s + sizeof(int32_t) * 2); d->level = level; int32_t* key = (int32_t*)SL_GET_NODE_KEY(pSkipList, d); key[0] = rand() % 1000000000; key[1] = key[0]; tSkipListPut(pSkipList, d); } printf("the first level of skip list is:\n"); tSkipListPrint(pSkipList, 1); printf("the sec level of skip list is:\n"); tSkipListPrint(pSkipList, 2); printf("the 5 level of skip list is:\n"); tSkipListPrint(pSkipList, 5); tSkipListDestroy(pSkipList); } void stringKeySkiplistTest() { const int32_t max_key_size = 12; SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_BINARY, max_key_size, 0, false, true, getkey); int32_t level = 0; int32_t headsize = 0; tSkipListRandNodeInfo(pSkipList, &level, &headsize); auto pNode = (SSkipListNode*)calloc(1, headsize + max_key_size + sizeof(double)); pNode->level = level; char* d = SL_GET_NODE_DATA(pNode); strncpy(d, "nyse", 5); *(double*)(d + max_key_size) = 12; tSkipListPut(pSkipList, pNode); tSkipListRandNodeInfo(pSkipList, &level, &headsize); pNode = (SSkipListNode*)calloc(1, headsize + max_key_size + sizeof(double)); pNode->level = level; d = SL_GET_NODE_DATA(pNode); strncpy(d, "beijing", 8); *(double*)(d + max_key_size) = 911; tSkipListPut(pSkipList, pNode); printf("level one------------------\n"); tSkipListPrint(pSkipList, 1); #if 0 SSkipListNode **pRes = NULL; int32_t ret = tSkipListGets(pSkipList, &key1, &pRes); assert(ret == 1); assert(strcmp(pRes[0]->key.pz, "beijing") == 0); assert(pRes[0]->key.nType == TSDB_DATA_TYPE_BINARY); tSkipListDestroyKey(&key1); tSkipListDestroyKey(&key); tSkipListDestroy(pSkipList); free(pRes); #endif tSkipListDestroy(pSkipList); int64_t s = taosGetTimestampUs(); pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_BINARY, 20, 0, false, true, getkey); char k[256] = {0}; int32_t total = 10000; for (int32_t i = 0; i < total; ++i) { int32_t n = sprintf(k, "abc_%d_%d", i, i); tSkipListRandNodeInfo(pSkipList, &level, &headsize); auto pNode = (SSkipListNode*)calloc(1, headsize + 20 + sizeof(double)); pNode->level = level; char* d = SL_GET_NODE_DATA(pNode); strncpy(d, k, strlen(k)); tSkipListPut(pSkipList, pNode); } int64_t e = taosGetTimestampUs(); printf("elapsed time:%" PRIu64 " us to insert %d data, avg:%f us\n", (e - s), total, (double)(e - s) / total); printf("level two------------------\n"); tSkipListPrint(pSkipList, 1); #if 0 SSkipListNode **pres = NULL; s = taosGetTimestampMs(); for (int32_t j = 0; j < total; ++j) { int32_t n = sprintf(k, "abc_%d_%d", j, j); key = tSkipListCreateKey(TSDB_DATA_TYPE_BINARY, k, n); int32_t num = tSkipListGets(pSkipList, &key, &pres); assert(num > 0); // tSkipListRemove(pSkipList, &key); tSkipListRemoveNode(pSkipList, pres[0]); if (num > 0) { tfree(pres); } } e = taosGetTimestampMs(); printf("elapsed time:%lldms\n", e - s); #endif tSkipListDestroy(pSkipList); } void skiplistPerformanceTest() { SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_DOUBLE, sizeof(double), 0, false, false, getkey); int32_t size = 1000000; int64_t prev = taosGetTimestampMs(); int64_t s = prev; int32_t level = 0; int32_t headsize = 0; int32_t unit = MAX_SKIP_LIST_LEVEL * POINTER_BYTES * 2 + sizeof(double) * 2 + sizeof(int16_t); char* total = (char*)calloc(1, unit * size); char* p = total; for (int32_t i = 0; i < size; ++i) { tSkipListRandNodeInfo(pSkipList, &level, &headsize); SSkipListNode* d = (SSkipListNode*)p; p += headsize + sizeof(double) * 2; d->level = level; double* v = (double*)SL_GET_NODE_DATA(d); v[0] = i * 0.997; v[1] = i * 0.997; tSkipListPut(pSkipList, d); if (i % 100000 == 0) { int64_t cur = taosGetTimestampMs(); int64_t elapsed = cur - prev; printf("add %d, elapsed time: %" PRIu64 " ms, avg elapsed:%f ms, total:%d\n", 100000, elapsed, elapsed / 100000.0, i); prev = cur; } } int64_t e = taosGetTimestampMs(); printf("total:%" PRIu64 " ms, avg:%f\n", e - s, (e - s) / (double)size); printf("max level of skiplist:%d, actually level:%d\n ", pSkipList->maxLevel, pSkipList->level); assert(tSkipListGetSize(pSkipList) == size); // printf("the level of skiplist is:\n"); // // printf("level two------------------\n"); // tSkipListPrint(pSkipList, 2); // // printf("level three------------------\n"); // tSkipListPrint(pSkipList, 3); // // printf("level four------------------\n"); // tSkipListPrint(pSkipList, 4); // // printf("level nine------------------\n"); // tSkipListPrint(pSkipList, 10); int64_t st = taosGetTimestampMs(); #if 0 for (int32_t i = 0; i < 100000; i += 1) { key.dKey = i * 0.997; tSkipListRemove(pSkipList, &key); } #endif int64_t et = taosGetTimestampMs(); printf("delete %d data from skiplist, elapased time:%" PRIu64 "ms\n", 10000, et - st); assert(tSkipListGetSize(pSkipList) == size); tSkipListDestroy(pSkipList); tfree(total); } // todo not support duplicated key yet void duplicatedKeyTest() { #if 0 SSkipListKey key; key.nType = TSDB_DATA_TYPE_INT; SSkipListNode **pNodes = NULL; SSkipList *pSkipList = tSkipListCreate(MAX_SKIP_LIST_LEVEL, TSDB_DATA_TYPE_INT, sizeof(int)); for (int32_t i = 0; i < 10000; ++i) { for (int32_t j = 0; j < 5; ++j) { key.i64Key = i; tSkipListPut(pSkipList, "", &key, 1); } } tSkipListPrint(pSkipList, 1); for (int32_t i = 0; i < 100; ++i) { key.i64Key = rand() % 1000; int32_t size = tSkipListGets(pSkipList, &key, &pNodes); assert(size == 5); tfree(pNodes); } tSkipListDestroy(pSkipList); #endif } } // namespace TEST(testCase, skiplist_test) { assert(sizeof(SSkipListKey) == 8); srand(time(NULL)); stringKeySkiplistTest(); doubleSkipListTest(); skiplistPerformanceTest(); duplicatedKeyTest(); randKeyTest(); // tSKipListQueryCond q; // q.upperBndRelOptr = true; // q.lowerBndRelOptr = true; // q.upperBnd.nType = TSDB_DATA_TYPE_DOUBLE; // q.lowerBnd.nType = TSDB_DATA_TYPE_DOUBLE; // q.lowerBnd.dKey = 120; // q.upperBnd.dKey = 171.989; /* int32_t size = tSkipListQuery(pSkipList, &q, &pNodes); for (int32_t i = 0; i < size; ++i) { printf("-----%lf\n", pNodes[i]->key.dKey); } printf("the range query result size is: %d\n", size); tfree(pNodes); SSkipListKey *pKeys = malloc(sizeof(SSkipListKey) * 20); for (int32_t i = 0; i < 8; i += 2) { pKeys[i].dKey = i * 0.997; pKeys[i].nType = TSDB_DATA_TYPE_DOUBLE; printf("%lf ", pKeys[i].dKey); } int32_t r = tSkipListPointQuery(pSkipList, pKeys, 8, EXCLUDE_POINT_QUERY, &pNodes); printf("\nthe exclude query result is: %d\n", r); for (int32_t i = 0; i < r; ++i) { // printf("%lf ", pNodes[i]->key.dKey); } tfree(pNodes); free(pKeys);*/ }