avl.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /**
  2. * Here is the assertions to ensure rightness of bst maintenance
  3. * After each insertion and delete, a tree must still be binary search tree,
  4. * and still remain balanced
  5. */
  6. #include <assert.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <mm_aspace.h>
  11. #include <mm_private.h>
  12. #define BUF_SIZE 1000000
  13. static void *_start;
  14. static void *_boundary;
  15. static int _count;
  16. static rt_varea_t _buf[BUF_SIZE];
  17. #define RT_ASSERT assert
  18. static void _print_varea(rt_varea_t varea, int depth)
  19. {
  20. if (depth == 0)
  21. {
  22. printf("%p ", varea->start);
  23. }
  24. else
  25. {
  26. rt_varea_t lchild = VAREA_ENTRY(varea->node.node.avl_left);
  27. rt_varea_t rchild = VAREA_ENTRY(varea->node.node.avl_right);
  28. depth--;
  29. if (lchild)
  30. _print_varea(lchild, depth);
  31. else
  32. printf("0x**** ");
  33. if (rchild)
  34. _print_varea(rchild, depth);
  35. else
  36. printf("0x**** ");
  37. }
  38. }
  39. static void _print_tree(rt_aspace_t aspace)
  40. {
  41. rt_varea_t varea = VAREA_ENTRY(aspace->tree.tree.root_node);
  42. if (!varea)
  43. return ;
  44. for (size_t i = 0; i < aspace->tree.tree.root_node->height; i++) {
  45. _print_varea(varea, i);
  46. putchar('\n');
  47. }
  48. return ;
  49. }
  50. static int _is_bst(rt_varea_t varea)
  51. {
  52. rt_varea_t lchild = VAREA_ENTRY(varea->node.node.avl_left);
  53. rt_varea_t rchild = VAREA_ENTRY(varea->node.node.avl_right);
  54. if (lchild)
  55. {
  56. RT_ASSERT(lchild->node.node.parent == &varea->node.node);
  57. RT_ASSERT(varea->start > lchild->start);
  58. }
  59. if (rchild)
  60. {
  61. RT_ASSERT(rchild->node.node.parent == &varea->node.node);
  62. if (varea->start >= rchild->start)
  63. {
  64. RT_ASSERT(0);
  65. }
  66. }
  67. return 1;
  68. }
  69. /* return height of current varea */
  70. static int _is_balanced(rt_varea_t varea)
  71. {
  72. if (!varea)
  73. {
  74. return 1;
  75. }
  76. rt_varea_t lchild = VAREA_ENTRY(varea->node.node.avl_left);
  77. rt_varea_t rchild = VAREA_ENTRY(varea->node.node.avl_right);
  78. int lbal = _is_balanced(lchild);
  79. int rbal = _is_balanced(rchild);
  80. if (lbal && rbal)
  81. {
  82. int diff = lbal - rbal;
  83. if (diff > 1 || diff < -1)
  84. {
  85. printf("lbal %d, rbal %d\n", lbal, rbal);
  86. return 0;
  87. }
  88. else
  89. {
  90. int height = lbal > rbal ? lbal : rbal;
  91. return height + 1;
  92. }
  93. }
  94. }
  95. /* add bst assertion */
  96. static int _check_asc_before(rt_varea_t varea, void *arg)
  97. {
  98. if (varea->start >= _start && (!_boundary || varea->start >= _boundary) && _is_bst(varea))
  99. {
  100. _buf[_count] = varea;
  101. _start = varea->start;
  102. _boundary = varea->start + varea->size;
  103. _count++;
  104. RT_ASSERT(_count < BUF_SIZE);
  105. }
  106. else
  107. {
  108. RT_ASSERT(0);
  109. }
  110. return 0;
  111. }
  112. static int _check_asc_before_rev(rt_varea_t varea, void *arg)
  113. {
  114. _count--;
  115. RT_ASSERT(varea == _buf[_count]);
  116. return 0;
  117. }
  118. static int _check_asc_after(rt_varea_t varea, void *arg)
  119. {
  120. rt_varea_t add_elem = (rt_varea_t)arg;
  121. if (!_is_bst(varea))
  122. {
  123. RT_ASSERT(0);
  124. }
  125. if (varea == _buf[_count])
  126. {
  127. _buf[_count] = 0;
  128. _count++;
  129. RT_ASSERT(_count < BUF_SIZE);
  130. }
  131. else if (add_elem && add_elem == varea)
  132. {
  133. /* adding, skip adding elem */
  134. }
  135. else if (!add_elem && varea == _buf[_count + 1])
  136. {
  137. /* deleting */
  138. _buf[_count] = 0;
  139. _buf[_count] = 0;
  140. _count++;
  141. RT_ASSERT(_count < BUF_SIZE);
  142. }
  143. else
  144. {
  145. printf("add_elem %p, varea %p, _count %d, in buf %p\n",
  146. add_elem->start, varea->start, _count, _buf[_count]);
  147. RT_ASSERT(0);
  148. }
  149. return 0;
  150. }
  151. static int _aspace_traversal(rt_aspace_t aspace, int (*fn)(rt_varea_t varea, void *arg), void *arg)
  152. {
  153. rt_varea_t varea = ASPACE_VAREA_FIRST(aspace);
  154. while (varea)
  155. {
  156. fn(varea, arg);
  157. varea = ASPACE_VAREA_NEXT(varea);
  158. }
  159. return 0;
  160. }
  161. static int _aspace_traversal_reverse(rt_aspace_t aspace, int (*fn)(rt_varea_t varea, void *arg), void *arg)
  162. {
  163. rt_varea_t varea = ASPACE_VAREA_LAST(aspace);
  164. while (varea)
  165. {
  166. fn(varea, arg);
  167. varea = ASPACE_VAREA_PREV(varea);
  168. }
  169. return 0;
  170. }
  171. static int _check_bst_before(struct rt_aspace *aspace, struct rt_varea *varea)
  172. {
  173. rt_varea_t root = VAREA_ENTRY(aspace->tree.tree.root_node);
  174. int height = _is_balanced(root);
  175. if (root)
  176. RT_ASSERT(height);
  177. memset(_buf, 0, sizeof(_buf)); // clear first avoiding none tree error
  178. _start = 0;
  179. _boundary = 0;
  180. _count = 0;
  181. _aspace_traversal(aspace, _check_asc_before, varea);
  182. int saved = _count;
  183. _aspace_traversal_reverse(aspace, _check_asc_before_rev, varea);
  184. _count = saved;
  185. return 1;
  186. }
  187. static int _check_bst_after(struct rt_aspace *aspace, struct rt_varea *varea, int isdel)
  188. {
  189. rt_varea_t root = VAREA_ENTRY(aspace->tree.tree.root_node);
  190. int height = _is_balanced(root);
  191. if (root)
  192. RT_ASSERT(height);
  193. int prev_count = _count;
  194. _start = 0;
  195. _boundary = 0;
  196. _count = 0;
  197. _aspace_traversal(aspace, _check_asc_after, isdel ? NULL : varea);
  198. _count = isdel ? _count : _count + 1;
  199. if (isdel)
  200. {
  201. RT_ASSERT(prev_count - 1 == _count);
  202. }
  203. else
  204. {
  205. RT_ASSERT(prev_count + 1 == _count);
  206. }
  207. return 1;
  208. }
  209. /* test library */
  210. #define RANDOM(n) (xrand() % (n))
  211. static unsigned int xseed = 0x11223344;
  212. static inline unsigned int xrand(void)
  213. {
  214. return (((xseed = xseed * 214013L + 2531011L) >> 16) & 0x7fffffff);
  215. }
  216. // generate keys
  217. static inline void init_random_keys(int *keys, int count, int seed)
  218. {
  219. int save_seed = time(NULL);
  220. int *array = (int*)malloc(sizeof(int) * count);
  221. int length = count, i;
  222. xseed = seed;
  223. for (i = 0; i < count; i++) {
  224. array[i] = i;
  225. }
  226. for (i = 0; i < length; i++) {
  227. int pos = xrand() % count;
  228. int key = array[pos];
  229. keys[i] = key;
  230. array[pos] = array[--count];
  231. }
  232. free(array);
  233. xseed = save_seed;
  234. }
  235. // A utility function to swap to integers
  236. static inline void swap (int *a, int *b)
  237. {
  238. int temp = *a;
  239. *a = *b;
  240. *b = temp;
  241. }
  242. // A function to generate a random permutation of arr[]
  243. static void randomize ( int arr[], int n )
  244. {
  245. // Use a different seed value so that we don't get same
  246. // result each time we run this program
  247. srand ( time(NULL) );
  248. // Start from the last element and swap one by one. We don't
  249. // need to run for the first element that's why i > 0
  250. for (int i = n-1; i > 0; i--)
  251. {
  252. // Pick a random index from 0 to i
  253. int j = rand() % (i+1);
  254. // Swap arr[i] with the element at random index
  255. swap(&arr[i], &arr[j]);
  256. }
  257. }
  258. /* time */
  259. #include <time.h>
  260. static int gettime(void)
  261. {
  262. struct timespec ts;
  263. clock_gettime(CLOCK_REALTIME_COARSE, &ts);
  264. time_t seconds = ts.tv_sec;
  265. int millisecond = ts.tv_nsec / 1000000;
  266. return millisecond + seconds * 1000;
  267. }
  268. /* Adapt Layer */
  269. /**
  270. * @brief Adapter Layer for lwp AVL BST
  271. */
  272. int _aspace_bst_init(struct rt_aspace *aspace)
  273. {
  274. aspace->tree.tree.root_node = AVL_ROOT;
  275. return 0;
  276. }
  277. static int compare_overlap(void *as, void *ae, void *bs, void *be)
  278. {
  279. LOG_D("as %lx, ae %lx, bs %lx, be %lx", as, ae, bs, be);
  280. int cmp;
  281. if (as > be)
  282. {
  283. cmp = 1;
  284. }
  285. else if (ae < bs)
  286. {
  287. cmp = -1;
  288. }
  289. else
  290. {
  291. cmp = 0;
  292. }
  293. LOG_D("ret %d", cmp);
  294. return cmp;
  295. }
  296. static int compare_exceed(void *as, void *ae, void *bs, void *be)
  297. {
  298. LOG_D("as %lx, ae %lx, bs %lx, be %lx", as, ae, bs, be);
  299. int cmp;
  300. if (as > bs)
  301. {
  302. cmp = 1;
  303. }
  304. else if (as < bs)
  305. {
  306. cmp = -1;
  307. }
  308. else
  309. {
  310. cmp = 0;
  311. }
  312. LOG_D("ret %d", cmp);
  313. return cmp;
  314. }
  315. static struct rt_varea *search(struct util_avl_root *root,
  316. struct _mm_range range,
  317. int (*compare)(void *as, void *ae, void *bs,
  318. void *be))
  319. {
  320. struct util_avl_struct *node = root->root_node;
  321. while (node)
  322. {
  323. rt_varea_t varea = VAREA_ENTRY(node);
  324. int cmp = compare(range.start, range.end, varea->start,
  325. varea->start + varea->size - 1);
  326. if (cmp < 0)
  327. {
  328. node = node->avl_left;
  329. }
  330. else if (cmp > 0)
  331. {
  332. node = node->avl_right;
  333. }
  334. else
  335. {
  336. return varea;
  337. }
  338. }
  339. return NULL;
  340. }
  341. struct rt_varea *_aspace_bst_search(struct rt_aspace *aspace, void *key)
  342. {
  343. struct util_avl_root *root = &aspace->tree.tree;
  344. struct _mm_range range = {key, key};
  345. return search(root, range, compare_overlap);
  346. }
  347. rt_varea_t _aspace_bst_search_exceed(struct rt_aspace *aspace, void *start)
  348. {
  349. struct util_avl_root *root = &aspace->tree.tree;
  350. struct util_avl_struct *node = root->root_node;
  351. rt_varea_t closest = NULL;
  352. ptrdiff_t min_off = PTRDIFF_MAX;
  353. while (node)
  354. {
  355. rt_varea_t varea = VAREA_ENTRY(node);
  356. void *va_s = varea->start;
  357. int cmp = compare_exceed(start, start, va_s, va_s);
  358. if (cmp < 0)
  359. {
  360. ptrdiff_t off = va_s - start;
  361. if (off < min_off)
  362. {
  363. min_off = off;
  364. closest = varea;
  365. }
  366. node = node->avl_left;
  367. }
  368. else if (cmp > 0)
  369. {
  370. node = node->avl_right;
  371. }
  372. else
  373. {
  374. return varea;
  375. }
  376. }
  377. return closest;
  378. }
  379. struct rt_varea *_aspace_bst_search_overlap(struct rt_aspace *aspace,
  380. struct _mm_range range)
  381. {
  382. struct util_avl_root *root = &aspace->tree.tree;
  383. return search(root, range, compare_overlap);
  384. }
  385. #ifdef ENABLE_DEBUG
  386. #include "bst_assert.h"
  387. #else
  388. #define _check_bst_before(x, ...)
  389. #define _check_bst_after(x, ...)
  390. #endif
  391. void _aspace_bst_insert(struct rt_aspace *aspace, struct rt_varea *varea)
  392. {
  393. struct util_avl_root *root = &aspace->tree.tree;
  394. struct util_avl_struct *current = NULL;
  395. struct util_avl_struct **next = &(root->root_node);
  396. rt_ubase_t key = (rt_ubase_t)varea->start;
  397. /* Figure out where to put new node */
  398. while (*next)
  399. {
  400. current = *next;
  401. struct rt_varea *data = VAREA_ENTRY(current);
  402. if (key < (rt_ubase_t)data->start)
  403. next = &(current->avl_left);
  404. else if (key > (rt_ubase_t)data->start)
  405. next = &(current->avl_right);
  406. else
  407. return;
  408. }
  409. /* Add new node and rebalance tree. */
  410. _check_bst_before(aspace, varea);
  411. util_avl_link(&varea->node.node, current, next);
  412. util_avl_rebalance(current, root);
  413. _check_bst_after(aspace, varea, 0);
  414. return;
  415. }
  416. void _aspace_bst_remove(struct rt_aspace *aspace, struct rt_varea *varea)
  417. {
  418. struct util_avl_struct *node = &varea->node.node;
  419. _check_bst_before(aspace, varea);
  420. util_avl_remove(node, &aspace->tree.tree);
  421. _check_bst_after(aspace, varea, 1);
  422. }
  423. struct rt_aspace aspace;
  424. /**
  425. * @brief Simulate environment of varea and BSTs
  426. */
  427. /* test data set */
  428. int *dataset;
  429. int loop_count;
  430. /* preallocate varea to decrease influence by malloc routine */
  431. struct rt_varea *_varea_buf;
  432. #define STOPWATCH(fun, time) do { \
  433. unsigned int _time; \
  434. _time = gettime(); \
  435. fun(); \
  436. _time = gettime()-_time; \
  437. time = _time; \
  438. } while (0);
  439. static void init_test(void)
  440. {
  441. _aspace_bst_init(&aspace);
  442. dataset = malloc(loop_count * sizeof(*dataset));
  443. assert(dataset);
  444. _varea_buf = malloc(loop_count * sizeof(*_varea_buf));
  445. assert(_varea_buf);
  446. init_random_keys(dataset, loop_count, 0xabcdabcd);
  447. }
  448. static void insert_test(void)
  449. {
  450. for (size_t i = 0; i < loop_count; i++)
  451. {
  452. struct rt_varea *varea;
  453. varea = &_varea_buf[i];
  454. varea->start = (void *)(uintptr_t)dataset[i];
  455. varea->size = 1;
  456. _aspace_bst_insert(&aspace, varea);
  457. }
  458. }
  459. static void search_test(void)
  460. {
  461. for (size_t i = 0; i < loop_count; i++)
  462. {
  463. void *start = (void *)(uintptr_t)dataset[i];
  464. struct rt_varea *varea;
  465. varea = _aspace_bst_search(&aspace, start);
  466. assert(varea);
  467. assert(varea->start == start);
  468. }
  469. }
  470. static void delete_test(void)
  471. {
  472. for (size_t i = 0; i < loop_count; i++)
  473. {
  474. void *start = (void *)(uintptr_t)dataset[i];
  475. struct rt_varea *varea;
  476. varea = _aspace_bst_search(&aspace, start);
  477. _aspace_bst_remove(&aspace, varea);
  478. }
  479. }
  480. static void cleanup(void)
  481. {
  482. free(dataset);
  483. free(_varea_buf);
  484. }
  485. int main(int argc, char *argv[])
  486. {
  487. if (argc == 2)
  488. {
  489. rt_sscanf(argv[1], "%d", &loop_count);
  490. }
  491. else
  492. {
  493. loop_count = 1000;
  494. }
  495. puts("Benchmark");
  496. printf("looping times: %d\n", loop_count);
  497. init_test();
  498. int endurance;
  499. STOPWATCH(insert_test, endurance);
  500. printf("Insertion: %d ms\n", endurance);
  501. randomize(dataset, loop_count);
  502. STOPWATCH(search_test, endurance);
  503. printf("Search: %d ms\n", endurance);
  504. randomize(dataset, loop_count);
  505. STOPWATCH(delete_test, endurance);
  506. printf("Delete: %d ms\n", endurance);
  507. cleanup();
  508. puts("Benchmark exit");
  509. return 0;
  510. }