Guest User

Untitled

a guest
Dec 10th, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.78 KB | None | 0 0
  1. #include <sys/time.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5.  
  6. #include "rope.h"
  7. #include "tests.h"
  8.  
  9. #include <ext/rope>
  10.  
  11. // Wrapper for rope
  12. static void *_rope_create() {
  13. return rope_new();
  14. }
  15.  
  16. static void _rope_insert(void *r, size_t pos, const uint8_t *str) {
  17. rope_insert((rope *)r, pos, str);
  18. }
  19. static void _rope_del(void *r, size_t pos, size_t len) {
  20. rope_del((rope *)r, pos, len);
  21. }
  22. static void _rope_destroy(void *r) {
  23. rope_free((rope *)r);
  24. }
  25.  
  26. static size_t _rope_num_chars(void *r) {
  27. return rope_char_count((rope *)r);
  28. }
  29.  
  30. // Wrapper for a vector-based string
  31.  
  32. // Private rope methods, stolen for utf8 support in the string.
  33. static size_t codepoint_size(uint8_t byte) {
  34. if (byte <= 0x7f) { return 1; }
  35. else if (byte <= 0xdf) { return 2; }
  36. else if (byte <= 0xef) { return 3; }
  37. else if (byte <= 0xf7) { return 4; }
  38. else if (byte <= 0xfb) { return 5; }
  39. else if (byte <= 0xfd) { return 6; }
  40. else {
  41. // The codepoint is invalid... what do?
  42. //assert(0);
  43. return 1;
  44. }
  45. }
  46.  
  47. // This little function counts how many bytes the some characters take up.
  48. static size_t count_bytes_in_chars(const uint8_t *str, size_t num_chars) {
  49. const uint8_t *p = str;
  50. for (int i = 0; i < num_chars; i++) {
  51. p += codepoint_size(*p);
  52. }
  53. return p - str;
  54. }
  55.  
  56. static size_t utf8_strlen(const uint8_t *str) {
  57. const uint8_t *p = str;
  58. while (*p) {
  59. p += codepoint_size(*p);
  60. }
  61. return p - str;
  62. }
  63.  
  64. typedef struct {
  65. uint8_t *mem;
  66. size_t capacity;
  67. size_t len;
  68. size_t num_chars;
  69. } _string;
  70.  
  71. static void *_str_create() {
  72. _string *s = (_string *)malloc(sizeof(_string));
  73. s->capacity = 64; // A reasonable capacity considering...
  74. s->mem = (uint8_t *)malloc(s->capacity);
  75. s->len = 0;
  76. s->num_chars = 0;
  77. return s;
  78. }
  79.  
  80. static void _str_insert(void *r, size_t pos, const uint8_t *str) {
  81. _string *s = (_string *)r;
  82.  
  83. size_t num_inserted_bytes = strlen((char *)str);
  84. // Offset to insert at in the string.
  85. size_t offset = count_bytes_in_chars(s->mem, pos);
  86. size_t end_size = s->len - offset;
  87.  
  88. // Resize if needed.
  89. s->len += num_inserted_bytes;
  90. if (s->len > s->capacity) {
  91. while (s->len > s->capacity) {
  92. s->capacity *= 2;
  93. }
  94. s->mem = (uint8_t *)realloc(s->mem, s->capacity);
  95. }
  96. s->num_chars += utf8_strlen(str);
  97.  
  98. memmove(&s->mem[offset + num_inserted_bytes], &s->mem[offset], end_size);
  99. memcpy(&s->mem[offset], str, num_inserted_bytes);
  100. }
  101.  
  102. static void _str_del(void *r, size_t pos, size_t len) {
  103. _string *s = (_string *)r;
  104.  
  105. // Offset to delete at in the string.
  106. size_t offset = count_bytes_in_chars(s->mem, pos);
  107. size_t num_bytes = count_bytes_in_chars(s->mem + offset, len);
  108. size_t end_size = s->len - offset - num_bytes;
  109.  
  110. memmove(&s->mem[offset], &s->mem[offset + num_bytes], end_size);
  111. s->len -= num_bytes;
  112. s->num_chars -= len;
  113. }
  114.  
  115. static void _str_destroy(void *r) {
  116. _string *s = (_string *)r;
  117. free(s->mem);
  118. free(s);
  119. }
  120.  
  121. static size_t _str_num_chars(void *r) {
  122. _string *s = (_string *)r;
  123. return s->num_chars;
  124. }
  125.  
  126. // SGI C++ rope
  127. static void *_sgi_create() {
  128. return new __gnu_cxx::crope();
  129. }
  130.  
  131. static void _sgi_insert(void *r, size_t pos, const uint8_t *str) {
  132. __gnu_cxx::crope *rope = (__gnu_cxx::crope *)r;
  133. rope->insert(pos, (const char *)str);
  134. }
  135. static void _sgi_del(void *r, size_t pos, size_t len) {
  136. __gnu_cxx::crope *rope = (__gnu_cxx::crope *)r;
  137. rope->erase(pos, len);
  138. }
  139. static void _sgi_destroy(void *r) {
  140. __gnu_cxx::crope *rope = (__gnu_cxx::crope *)r;
  141. delete rope;
  142. }
  143.  
  144. static size_t _sgi_num_chars(void *r) {
  145. __gnu_cxx::crope *rope = (__gnu_cxx::crope *)r;
  146. return rope->size();
  147. }
  148.  
  149.  
  150. struct rope_implementation {
  151. const char *name;
  152. void* (*create)();
  153. void (*insert)(void *r, size_t pos, const uint8_t *str);
  154. void (*del)(void *r, size_t pos, size_t len);
  155. void (*destroy)(void *r);
  156. size_t (*num_chars)(void *r);
  157. } types[] = {
  158. { "librope", &_rope_create, &_rope_insert, &_rope_del, &_rope_destroy, &_rope_num_chars },
  159. { "c string", &_str_create, &_str_insert, &_str_del, &_str_destroy, &_str_num_chars },
  160. { "sgirope", &_sgi_create, &_sgi_insert, &_sgi_del, &_sgi_destroy, &_sgi_num_chars },
  161. };
  162.  
  163. void benchmark() {
  164. printf("Benchmarking...\n");
  165.  
  166. //long iterations = 20000000;
  167. long iterations = 500000;
  168. struct timeval start, end;
  169.  
  170. uint8_t *strings[100];
  171. for (int i = 0; i < 100; i++) {
  172. size_t len = 1 + random() % 2;//i * i + 1;
  173. strings[i] = (uint8_t *)calloc(1, len + 1);
  174. random_ascii_string(strings[i], len + 1);
  175. }
  176.  
  177. // We should pick the same random sequence each benchmark run.
  178. unsigned long *rvals = (unsigned long *)malloc(sizeof(long) * iterations);
  179. for (int i = 0; i < iterations; i++) {
  180. rvals[i] = random();
  181. }
  182.  
  183. for (int t = 0; t < sizeof(types) / sizeof(types[0]); t++) {
  184. //for (int t = 0; t < 1; t++) {
  185. printf("benchmarking %s\n", types[t].name);
  186. void *r = types[t].create();
  187. gettimeofday(&start, NULL);
  188.  
  189. for (long i = 0; i < iterations; i++) {
  190. if (types[t].num_chars(r) == 0 || i % 20 > 0) {
  191. // insert. (Inserts are way more common in practice than deletes.)
  192. uint8_t *str = strings[i % 100];
  193. types[t].insert(r, rvals[i] % (types[t].num_chars(r) + 1), str);
  194. } else {
  195. size_t pos = rvals[i] % types[t].num_chars(r);
  196. size_t length = MIN(types[t].num_chars(r) - pos, 1 + (~rvals[i]) % 53);
  197. types[t].del(r, pos, length);
  198. }
  199.  
  200. //printf("%s\n", rope_createcstr(r, NULL));
  201. }
  202.  
  203. gettimeofday(&end, NULL);
  204.  
  205. double elapsedTime = end.tv_sec - start.tv_sec;
  206. elapsedTime += (end.tv_usec - start.tv_usec) / 1e6;
  207. printf("did %ld iterations in %f ms: %f Miter/sec\n",
  208. iterations, elapsedTime * 1000, iterations / elapsedTime / 1000000);
  209. printf("final string length: %zi\n", types[t].num_chars(r));
  210.  
  211. types[t].destroy(r);
  212. }
  213.  
  214. for (int i = 0; i < 100; i++) {
  215. free(strings[i]);
  216. }
  217. }
Add Comment
Please, Sign In to add comment