homework-jianmu/source/util/test/skiplistTest.cpp

380 lines
10 KiB
C++

#include <gtest/gtest.h>
#include <limits.h>
#include <taosdef.h>
#include <tcompare.h>
#include <iostream>
#include "os.h"
#include "tmsg.h"
#include "tskiplist.h"
#include "tutil.h"
#if 0
namespace {
char* getkey(const void* data) { return (char*)(data); }
void doubleSkipListTest() {
SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_DOUBLE, sizeof(double),
getKeyComparFunc(TSDB_DATA_TYPE_DOUBLE), false, 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;
size = 0;
// tSkipListNewNodeInfo(pSkipList, &level, &size);
// auto d = (SSkipListNode*)taosMemoryCalloc(1, size + sizeof(double) * 2);
// d->level = level;
double key = 0.997;
tSkipListPut(pSkipList, &key);
}
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 * taosRand()) % 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) {
taosMemoryFreeClear(pNodes);
}
}
#endif
printf("double test end...\n");
tSkipListDestroy(pSkipList);
}
void randKeyTest() {
SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_INT, sizeof(int32_t), getKeyComparFunc(TSDB_DATA_TYPE_INT, TSDB_ORDER_ASC),
false, getkey);
int32_t size = 200000;
taosSeedRand(taosGetTimestampSec());
printf("generated %d keys is: \n", size);
for (int32_t i = 0; i < size; ++i) {
int32_t level = 0;
int32_t s = 0;
tSkipListNewNodeInfo(pSkipList, &level, &s);
auto d = (SSkipListNode*)taosMemoryCalloc(1, s + sizeof(int32_t) * 2);
d->level = level;
int32_t* key = (int32_t*)SL_GET_NODE_KEY(pSkipList, d);
key[0] = taosRand() % 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;
tSkipListNewNodeInfo(pSkipList, &level, &headsize);
auto pNode = (SSkipListNode*)taosMemoryCalloc(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);
tSkipListNewNodeInfo(pSkipList, &level, &headsize);
pNode = (SSkipListNode*)taosMemoryCalloc(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);
taosMemoryFree(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);
tSkipListNewNodeInfo(pSkipList, &level, &headsize);
auto pNode = (SSkipListNode*)taosMemoryCalloc(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) {
taosMemoryFreeClear(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*)taosMemoryCalloc(1, unit * size);
char* p = total;
for (int32_t i = 0; i < size; ++i) {
tSkipListNewNodeInfo(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(SL_GET_SIZE(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(SL_GET_SIZE(pSkipList) == size);
tSkipListDestroy(pSkipList);
taosMemoryFreeClear(total);
}
// todo not support duplicated key yet
void duplicatedKeyTest() {
SSkipList *pSkipList = tSkipListCreate(MAX_SKIP_LIST_LEVEL, TSDB_DATA_TYPE_INT, sizeof(int), true, false, true, getkey);
for (int32_t i = 0; i < 200; ++i) {
for (int32_t j = 0; j < 5; ++j) {
int32_t level, size;
tSkipListNewNodeInfo(pSkipList, &level, &size);
SSkipListNode* d = (SSkipListNode*)taosMemoryCalloc(1, size + sizeof(int32_t));
d->level = level;
int32_t* key = (int32_t*)SL_GET_NODE_KEY(pSkipList, d);
key[0] = i;
tSkipListPut(pSkipList, d);
}
}
for (int32_t i = 0; i < 100; ++i) {
SSkipListKey key;
SArray* nodes = tSkipListGet(pSkipList, (char*)(&i));
assert( taosArrayGetSize(nodes) == 5 );
taosArrayDestroy(nodes);
}
int32_t key = 101;
uint32_t num = tSkipListRemove(pSkipList, (char*)(&key));
assert(num == 5);
SArray* nodes = tSkipListGet(pSkipList, (char*)(&key));
assert( taosArrayGetSize(nodes) == 0 );
taosArrayDestroy(nodes);
key = 102;
SSkipListIterator* iter = tSkipListCreateIterFromVal(pSkipList, (char*)(&key), TSDB_DATA_TYPE_INT, TSDB_ORDER_ASC);
for(int i = 0; i < 6; i++) {
assert(tSkipListIterNext(iter) == true);
SSkipListNode* node = tSkipListIterGet(iter);
int32_t* val = (int32_t*)SL_GET_NODE_KEY(pSkipList, node);
assert((i < 5) == ((*val) == key));
}
tSkipListDestroyIter(iter);
iter = tSkipListCreateIterFromVal(pSkipList, (char*)(&key), TSDB_DATA_TYPE_INT, TSDB_ORDER_DESC);
for(int i = 0; i < 6; i++) {
assert(tSkipListIterNext(iter) == true);
SSkipListNode* node = tSkipListIterGet(iter);
int32_t* val = (int32_t*)SL_GET_NODE_KEY(pSkipList, node);
assert((i < 5) == ((*val) == key));
}
tSkipListDestroyIter(iter);
tSkipListDestroy(pSkipList);
}
} // namespace
TEST(testCase, skiplist_test) {
assert(sizeof(SSkipListKey) == 8);
taosSeedRand(taosGetTimestampSec());
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);
taosMemoryFreeClear(pNodes);
SSkipListKey *pKeys = taosMemoryMalloc(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);
}
taosMemoryFreeClear(pNodes);
taosMemoryFree(pKeys);*/
}
#endif