hdr_histogram.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. /**
  2. * hdr_histogram.c
  3. * Written by Michael Barker and released to the public domain,
  4. * as explained at http://creativecommons.org/publicdomain/zero/1.0/
  5. */
  6. #include <stdlib.h>
  7. #include <stdbool.h>
  8. #include <math.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdint.h>
  12. #include <errno.h>
  13. #include <inttypes.h>
  14. #include "hdr_histogram.h"
  15. #include "hdr_atomic.h"
  16. /* ###### ####### ## ## ## ## ######## ###### */
  17. /* ## ## ## ## ## ## ### ## ## ## ## */
  18. /* ## ## ## ## ## #### ## ## ## */
  19. /* ## ## ## ## ## ## ## ## ## ###### */
  20. /* ## ## ## ## ## ## #### ## ## */
  21. /* ## ## ## ## ## ## ## ### ## ## ## */
  22. /* ###### ####### ####### ## ## ## ###### */
  23. static int32_t normalize_index(const struct hdr_histogram* h, int32_t index)
  24. {
  25. int32_t normalized_index;
  26. int32_t adjustment = 0;
  27. if (h->normalizing_index_offset == 0)
  28. {
  29. return index;
  30. }
  31. normalized_index = index - h->normalizing_index_offset;
  32. if (normalized_index < 0)
  33. {
  34. adjustment = h->counts_len;
  35. }
  36. else if (normalized_index >= h->counts_len)
  37. {
  38. adjustment = -h->counts_len;
  39. }
  40. return normalized_index + adjustment;
  41. }
  42. static int64_t counts_get_direct(const struct hdr_histogram* h, int32_t index)
  43. {
  44. return h->counts[index];
  45. }
  46. static int64_t counts_get_normalised(const struct hdr_histogram* h, int32_t index)
  47. {
  48. return counts_get_direct(h, normalize_index(h, index));
  49. }
  50. static void counts_inc_normalised(
  51. struct hdr_histogram* h, int32_t index, int64_t value)
  52. {
  53. int32_t normalised_index = normalize_index(h, index);
  54. h->counts[normalised_index] += value;
  55. h->total_count += value;
  56. }
  57. static void counts_inc_normalised_atomic(
  58. struct hdr_histogram* h, int32_t index, int64_t value)
  59. {
  60. int32_t normalised_index = normalize_index(h, index);
  61. hdr_atomic_add_fetch_64(&h->counts[normalised_index], value);
  62. hdr_atomic_add_fetch_64(&h->total_count, value);
  63. }
  64. static void update_min_max(struct hdr_histogram* h, int64_t value)
  65. {
  66. h->min_value = (value < h->min_value && value != 0) ? value : h->min_value;
  67. h->max_value = (value > h->max_value) ? value : h->max_value;
  68. }
  69. static void update_min_max_atomic(struct hdr_histogram* h, int64_t value)
  70. {
  71. int64_t current_min_value;
  72. int64_t current_max_value;
  73. do
  74. {
  75. current_min_value = hdr_atomic_load_64(&h->min_value);
  76. if (0 == value || current_min_value <= value)
  77. {
  78. break;
  79. }
  80. }
  81. while (!hdr_atomic_compare_exchange_64(&h->min_value, &current_min_value, value));
  82. do
  83. {
  84. current_max_value = hdr_atomic_load_64(&h->max_value);
  85. if (value <= current_max_value)
  86. {
  87. break;
  88. }
  89. }
  90. while (!hdr_atomic_compare_exchange_64(&h->max_value, &current_max_value, value));
  91. }
  92. /* ## ## ######## #### ## #### ######## ## ## */
  93. /* ## ## ## ## ## ## ## ## ## */
  94. /* ## ## ## ## ## ## ## #### */
  95. /* ## ## ## ## ## ## ## ## */
  96. /* ## ## ## ## ## ## ## ## */
  97. /* ## ## ## ## ## ## ## ## */
  98. /* ####### ## #### ######## #### ## ## */
  99. static int64_t power(int64_t base, int64_t exp)
  100. {
  101. int64_t result = 1;
  102. while(exp)
  103. {
  104. result *= base; exp--;
  105. }
  106. return result;
  107. }
  108. #if defined(_MSC_VER)
  109. # if defined(_WIN64)
  110. # pragma intrinsic(_BitScanReverse64)
  111. # else
  112. # pragma intrinsic(_BitScanReverse)
  113. # endif
  114. #endif
  115. static int32_t count_leading_zeros_64(int64_t value)
  116. {
  117. #if defined(_MSC_VER)
  118. uint32_t leading_zero = 0;
  119. #if defined(_WIN64)
  120. _BitScanReverse64(&leading_zero, value);
  121. #else
  122. uint32_t high = value >> 32;
  123. if (_BitScanReverse(&leading_zero, high))
  124. {
  125. leading_zero += 32;
  126. }
  127. else
  128. {
  129. uint32_t low = value & 0x00000000FFFFFFFF;
  130. _BitScanReverse(&leading_zero, low);
  131. }
  132. #endif
  133. return 63 - leading_zero; /* smallest power of 2 containing value */
  134. #else
  135. return __builtin_clzll(value); /* smallest power of 2 containing value */
  136. #endif
  137. }
  138. static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value)
  139. {
  140. int32_t pow2ceiling = 64 - count_leading_zeros_64(value | h->sub_bucket_mask); /* smallest power of 2 containing value */
  141. return pow2ceiling - h->unit_magnitude - (h->sub_bucket_half_count_magnitude + 1);
  142. }
  143. static int32_t get_sub_bucket_index(int64_t value, int32_t bucket_index, int32_t unit_magnitude)
  144. {
  145. return (int32_t)(value >> (bucket_index + unit_magnitude));
  146. }
  147. static int32_t counts_index(const struct hdr_histogram* h, int32_t bucket_index, int32_t sub_bucket_index)
  148. {
  149. /* Calculate the index for the first entry in the bucket: */
  150. /* (The following is the equivalent of ((bucket_index + 1) * subBucketHalfCount) ): */
  151. int32_t bucket_base_index = (bucket_index + 1) << h->sub_bucket_half_count_magnitude;
  152. /* Calculate the offset in the bucket: */
  153. int32_t offset_in_bucket = sub_bucket_index - h->sub_bucket_half_count;
  154. /* The following is the equivalent of ((sub_bucket_index - subBucketHalfCount) + bucketBaseIndex; */
  155. return bucket_base_index + offset_in_bucket;
  156. }
  157. static int64_t value_from_index(int32_t bucket_index, int32_t sub_bucket_index, int32_t unit_magnitude)
  158. {
  159. return ((int64_t) sub_bucket_index) << (bucket_index + unit_magnitude);
  160. }
  161. int32_t counts_index_for(const struct hdr_histogram* h, int64_t value)
  162. {
  163. int32_t bucket_index = get_bucket_index(h, value);
  164. int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
  165. return counts_index(h, bucket_index, sub_bucket_index);
  166. }
  167. int64_t hdr_value_at_index(const struct hdr_histogram *h, int32_t index)
  168. {
  169. int32_t bucket_index = (index >> h->sub_bucket_half_count_magnitude) - 1;
  170. int32_t sub_bucket_index = (index & (h->sub_bucket_half_count - 1)) + h->sub_bucket_half_count;
  171. if (bucket_index < 0)
  172. {
  173. sub_bucket_index -= h->sub_bucket_half_count;
  174. bucket_index = 0;
  175. }
  176. return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
  177. }
  178. int64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_t value)
  179. {
  180. int32_t bucket_index = get_bucket_index(h, value);
  181. int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
  182. int32_t adjusted_bucket = (sub_bucket_index >= h->sub_bucket_count) ? (bucket_index + 1) : bucket_index;
  183. return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
  184. }
  185. static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
  186. {
  187. int32_t bucket_index = get_bucket_index(h, value);
  188. int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
  189. return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
  190. }
  191. int64_t hdr_next_non_equivalent_value(const struct hdr_histogram *h, int64_t value)
  192. {
  193. return lowest_equivalent_value(h, value) + hdr_size_of_equivalent_value_range(h, value);
  194. }
  195. static int64_t highest_equivalent_value(const struct hdr_histogram* h, int64_t value)
  196. {
  197. return hdr_next_non_equivalent_value(h, value) - 1;
  198. }
  199. int64_t hdr_median_equivalent_value(const struct hdr_histogram *h, int64_t value)
  200. {
  201. return lowest_equivalent_value(h, value) + (hdr_size_of_equivalent_value_range(h, value) >> 1);
  202. }
  203. static int64_t non_zero_min(const struct hdr_histogram* h)
  204. {
  205. if (INT64_MAX == h->min_value)
  206. {
  207. return INT64_MAX;
  208. }
  209. return lowest_equivalent_value(h, h->min_value);
  210. }
  211. void hdr_reset_internal_counters(struct hdr_histogram* h)
  212. {
  213. int min_non_zero_index = -1;
  214. int max_index = -1;
  215. int64_t observed_total_count = 0;
  216. int i;
  217. for (i = 0; i < h->counts_len; i++)
  218. {
  219. int64_t count_at_index;
  220. if ((count_at_index = counts_get_direct(h, i)) > 0)
  221. {
  222. observed_total_count += count_at_index;
  223. max_index = i;
  224. if (min_non_zero_index == -1 && i != 0)
  225. {
  226. min_non_zero_index = i;
  227. }
  228. }
  229. }
  230. if (max_index == -1)
  231. {
  232. h->max_value = 0;
  233. }
  234. else
  235. {
  236. int64_t max_value = hdr_value_at_index(h, max_index);
  237. h->max_value = highest_equivalent_value(h, max_value);
  238. }
  239. if (min_non_zero_index == -1)
  240. {
  241. h->min_value = INT64_MAX;
  242. }
  243. else
  244. {
  245. h->min_value = hdr_value_at_index(h, min_non_zero_index);
  246. }
  247. h->total_count = observed_total_count;
  248. }
  249. static int32_t buckets_needed_to_cover_value(int64_t value, int32_t sub_bucket_count, int32_t unit_magnitude)
  250. {
  251. int64_t smallest_untrackable_value = ((int64_t) sub_bucket_count) << unit_magnitude;
  252. int32_t buckets_needed = 1;
  253. while (smallest_untrackable_value <= value)
  254. {
  255. if (smallest_untrackable_value > INT64_MAX / 2)
  256. {
  257. return buckets_needed + 1;
  258. }
  259. smallest_untrackable_value <<= 1;
  260. buckets_needed++;
  261. }
  262. return buckets_needed;
  263. }
  264. /* ## ## ######## ## ## ####### ######## ## ## */
  265. /* ### ### ## ### ### ## ## ## ## ## ## */
  266. /* #### #### ## #### #### ## ## ## ## #### */
  267. /* ## ### ## ###### ## ### ## ## ## ######## ## */
  268. /* ## ## ## ## ## ## ## ## ## ## */
  269. /* ## ## ## ## ## ## ## ## ## ## */
  270. /* ## ## ######## ## ## ####### ## ## ## */
  271. int hdr_calculate_bucket_config(
  272. int64_t lowest_trackable_value,
  273. int64_t highest_trackable_value,
  274. int significant_figures,
  275. struct hdr_histogram_bucket_config* cfg)
  276. {
  277. int32_t sub_bucket_count_magnitude;
  278. int64_t largest_value_with_single_unit_resolution;
  279. if (lowest_trackable_value < 1 ||
  280. significant_figures < 1 || 5 < significant_figures ||
  281. lowest_trackable_value * 2 > highest_trackable_value)
  282. {
  283. return EINVAL;
  284. }
  285. cfg->lowest_trackable_value = lowest_trackable_value;
  286. cfg->significant_figures = significant_figures;
  287. cfg->highest_trackable_value = highest_trackable_value;
  288. largest_value_with_single_unit_resolution = 2 * power(10, significant_figures);
  289. sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2));
  290. cfg->sub_bucket_half_count_magnitude = ((sub_bucket_count_magnitude > 1) ? sub_bucket_count_magnitude : 1) - 1;
  291. cfg->unit_magnitude = (int32_t) floor(log((double)lowest_trackable_value) / log(2));
  292. cfg->sub_bucket_count = (int32_t) pow(2, (cfg->sub_bucket_half_count_magnitude + 1));
  293. cfg->sub_bucket_half_count = cfg->sub_bucket_count / 2;
  294. cfg->sub_bucket_mask = ((int64_t) cfg->sub_bucket_count - 1) << cfg->unit_magnitude;
  295. if (cfg->unit_magnitude + cfg->sub_bucket_half_count_magnitude > 61)
  296. {
  297. return EINVAL;
  298. }
  299. cfg->bucket_count = buckets_needed_to_cover_value(highest_trackable_value, cfg->sub_bucket_count, (int32_t)cfg->unit_magnitude);
  300. cfg->counts_len = (cfg->bucket_count + 1) * (cfg->sub_bucket_count / 2);
  301. return 0;
  302. }
  303. void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg)
  304. {
  305. h->lowest_trackable_value = cfg->lowest_trackable_value;
  306. h->highest_trackable_value = cfg->highest_trackable_value;
  307. h->unit_magnitude = (int32_t)cfg->unit_magnitude;
  308. h->significant_figures = (int32_t)cfg->significant_figures;
  309. h->sub_bucket_half_count_magnitude = cfg->sub_bucket_half_count_magnitude;
  310. h->sub_bucket_half_count = cfg->sub_bucket_half_count;
  311. h->sub_bucket_mask = cfg->sub_bucket_mask;
  312. h->sub_bucket_count = cfg->sub_bucket_count;
  313. h->min_value = INT64_MAX;
  314. h->max_value = 0;
  315. h->normalizing_index_offset = 0;
  316. h->conversion_ratio = 1.0;
  317. h->bucket_count = cfg->bucket_count;
  318. h->counts_len = cfg->counts_len;
  319. h->total_count = 0;
  320. }
  321. int hdr_init(
  322. int64_t lowest_trackable_value,
  323. int64_t highest_trackable_value,
  324. int significant_figures,
  325. struct hdr_histogram** result)
  326. {
  327. int64_t* counts;
  328. struct hdr_histogram_bucket_config cfg;
  329. struct hdr_histogram* histogram;
  330. int r = hdr_calculate_bucket_config(lowest_trackable_value, highest_trackable_value, significant_figures, &cfg);
  331. if (r)
  332. {
  333. return r;
  334. }
  335. counts = (int64_t*) calloc((size_t) cfg.counts_len, sizeof(int64_t));
  336. if (!counts)
  337. {
  338. return ENOMEM;
  339. }
  340. histogram = (struct hdr_histogram*) calloc(1, sizeof(struct hdr_histogram));
  341. if (!histogram)
  342. {
  343. free(counts);
  344. return ENOMEM;
  345. }
  346. histogram->counts = counts;
  347. hdr_init_preallocated(histogram, &cfg);
  348. *result = histogram;
  349. return 0;
  350. }
  351. void hdr_close(struct hdr_histogram* h)
  352. {
  353. if (h) {
  354. free(h->counts);
  355. free(h);
  356. }
  357. }
  358. int hdr_alloc(int64_t highest_trackable_value, int significant_figures, struct hdr_histogram** result)
  359. {
  360. return hdr_init(1, highest_trackable_value, significant_figures, result);
  361. }
  362. /* reset a histogram to zero. */
  363. void hdr_reset(struct hdr_histogram *h)
  364. {
  365. h->total_count=0;
  366. h->min_value = INT64_MAX;
  367. h->max_value = 0;
  368. memset(h->counts, 0, (sizeof(int64_t) * h->counts_len));
  369. }
  370. size_t hdr_get_memory_size(struct hdr_histogram *h)
  371. {
  372. return sizeof(struct hdr_histogram) + h->counts_len * sizeof(int64_t);
  373. }
  374. /* ## ## ######## ######## ### ######## ######## ###### */
  375. /* ## ## ## ## ## ## ## ## ## ## ## ## */
  376. /* ## ## ## ## ## ## ## ## ## ## ## */
  377. /* ## ## ######## ## ## ## ## ## ###### ###### */
  378. /* ## ## ## ## ## ######### ## ## ## */
  379. /* ## ## ## ## ## ## ## ## ## ## ## */
  380. /* ####### ## ######## ## ## ## ######## ###### */
  381. bool hdr_record_value(struct hdr_histogram* h, int64_t value)
  382. {
  383. return hdr_record_values(h, value, 1);
  384. }
  385. bool hdr_record_value_atomic(struct hdr_histogram* h, int64_t value)
  386. {
  387. return hdr_record_values_atomic(h, value, 1);
  388. }
  389. bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count)
  390. {
  391. int32_t counts_index;
  392. if (value < 0)
  393. {
  394. return false;
  395. }
  396. counts_index = counts_index_for(h, value);
  397. if (counts_index < 0 || h->counts_len <= counts_index)
  398. {
  399. return false;
  400. }
  401. counts_inc_normalised(h, counts_index, count);
  402. update_min_max(h, value);
  403. return true;
  404. }
  405. bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count)
  406. {
  407. int32_t counts_index;
  408. if (value < 0)
  409. {
  410. return false;
  411. }
  412. counts_index = counts_index_for(h, value);
  413. if (counts_index < 0 || h->counts_len <= counts_index)
  414. {
  415. return false;
  416. }
  417. counts_inc_normalised_atomic(h, counts_index, count);
  418. update_min_max_atomic(h, value);
  419. return true;
  420. }
  421. bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
  422. {
  423. return hdr_record_corrected_values(h, value, 1, expected_interval);
  424. }
  425. bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
  426. {
  427. return hdr_record_corrected_values_atomic(h, value, 1, expected_interval);
  428. }
  429. bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
  430. {
  431. int64_t missing_value;
  432. if (!hdr_record_values(h, value, count))
  433. {
  434. return false;
  435. }
  436. if (expected_interval <= 0 || value <= expected_interval)
  437. {
  438. return true;
  439. }
  440. missing_value = value - expected_interval;
  441. for (; missing_value >= expected_interval; missing_value -= expected_interval)
  442. {
  443. if (!hdr_record_values(h, missing_value, count))
  444. {
  445. return false;
  446. }
  447. }
  448. return true;
  449. }
  450. bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
  451. {
  452. int64_t missing_value;
  453. if (!hdr_record_values_atomic(h, value, count))
  454. {
  455. return false;
  456. }
  457. if (expected_interval <= 0 || value <= expected_interval)
  458. {
  459. return true;
  460. }
  461. missing_value = value - expected_interval;
  462. for (; missing_value >= expected_interval; missing_value -= expected_interval)
  463. {
  464. if (!hdr_record_values_atomic(h, missing_value, count))
  465. {
  466. return false;
  467. }
  468. }
  469. return true;
  470. }
  471. int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from)
  472. {
  473. struct hdr_iter iter;
  474. int64_t dropped = 0;
  475. hdr_iter_recorded_init(&iter, from);
  476. while (hdr_iter_next(&iter))
  477. {
  478. int64_t value = iter.value;
  479. int64_t count = iter.count;
  480. if (!hdr_record_values(h, value, count))
  481. {
  482. dropped += count;
  483. }
  484. }
  485. return dropped;
  486. }
  487. int64_t hdr_add_while_correcting_for_coordinated_omission(
  488. struct hdr_histogram* h, struct hdr_histogram* from, int64_t expected_interval)
  489. {
  490. struct hdr_iter iter;
  491. int64_t dropped = 0;
  492. hdr_iter_recorded_init(&iter, from);
  493. while (hdr_iter_next(&iter))
  494. {
  495. int64_t value = iter.value;
  496. int64_t count = iter.count;
  497. if (!hdr_record_corrected_values(h, value, count, expected_interval))
  498. {
  499. dropped += count;
  500. }
  501. }
  502. return dropped;
  503. }
  504. /* ## ## ### ## ## ## ######## ###### */
  505. /* ## ## ## ## ## ## ## ## ## ## */
  506. /* ## ## ## ## ## ## ## ## ## */
  507. /* ## ## ## ## ## ## ## ###### ###### */
  508. /* ## ## ######### ## ## ## ## ## */
  509. /* ## ## ## ## ## ## ## ## ## ## */
  510. /* ### ## ## ######## ####### ######## ###### */
  511. int64_t hdr_max(const struct hdr_histogram* h)
  512. {
  513. if (0 == h->max_value)
  514. {
  515. return 0;
  516. }
  517. return highest_equivalent_value(h, h->max_value);
  518. }
  519. int64_t hdr_min(const struct hdr_histogram* h)
  520. {
  521. if (0 < hdr_count_at_index(h, 0))
  522. {
  523. return 0;
  524. }
  525. return non_zero_min(h);
  526. }
  527. int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
  528. {
  529. struct hdr_iter iter;
  530. int64_t total = 0;
  531. double requested_percentile = percentile < 100.0 ? percentile : 100.0;
  532. int64_t count_at_percentile =
  533. (int64_t) (((requested_percentile / 100) * h->total_count) + 0.5);
  534. count_at_percentile = count_at_percentile > 1 ? count_at_percentile : 1;
  535. hdr_iter_init(&iter, h);
  536. while (hdr_iter_next(&iter))
  537. {
  538. total += iter.count;
  539. if (total >= count_at_percentile)
  540. {
  541. int64_t value_from_index = iter.value;
  542. return highest_equivalent_value(h, value_from_index);
  543. }
  544. }
  545. return 0;
  546. }
  547. double hdr_mean(const struct hdr_histogram* h)
  548. {
  549. struct hdr_iter iter;
  550. int64_t total = 0;
  551. hdr_iter_init(&iter, h);
  552. while (hdr_iter_next(&iter))
  553. {
  554. if (0 != iter.count)
  555. {
  556. total += iter.count * hdr_median_equivalent_value(h, iter.value);
  557. }
  558. }
  559. return (total * 1.0) / h->total_count;
  560. }
  561. double hdr_stddev(const struct hdr_histogram* h)
  562. {
  563. double mean = hdr_mean(h);
  564. double geometric_dev_total = 0.0;
  565. struct hdr_iter iter;
  566. hdr_iter_init(&iter, h);
  567. while (hdr_iter_next(&iter))
  568. {
  569. if (0 != iter.count)
  570. {
  571. double dev = (hdr_median_equivalent_value(h, iter.value) * 1.0) - mean;
  572. geometric_dev_total += (dev * dev) * iter.count;
  573. }
  574. }
  575. return sqrt(geometric_dev_total / h->total_count);
  576. }
  577. bool hdr_values_are_equivalent(const struct hdr_histogram* h, int64_t a, int64_t b)
  578. {
  579. return lowest_equivalent_value(h, a) == lowest_equivalent_value(h, b);
  580. }
  581. int64_t hdr_lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
  582. {
  583. return lowest_equivalent_value(h, value);
  584. }
  585. int64_t hdr_count_at_value(const struct hdr_histogram* h, int64_t value)
  586. {
  587. return counts_get_normalised(h, counts_index_for(h, value));
  588. }
  589. int64_t hdr_count_at_index(const struct hdr_histogram* h, int32_t index)
  590. {
  591. return counts_get_normalised(h, index);
  592. }
  593. /* #### ######## ######## ######## ### ######## ####### ######## ###### */
  594. /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
  595. /* ## ## ## ## ## ## ## ## ## ## ## ## ## */
  596. /* ## ## ###### ######## ## ## ## ## ## ######## ###### */
  597. /* ## ## ## ## ## ######### ## ## ## ## ## ## */
  598. /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
  599. /* #### ## ######## ## ## ## ## ## ####### ## ## ###### */
  600. static bool has_buckets(struct hdr_iter* iter)
  601. {
  602. return iter->counts_index < iter->h->counts_len;
  603. }
  604. static bool has_next(struct hdr_iter* iter)
  605. {
  606. return iter->cumulative_count < iter->total_count;
  607. }
  608. static bool move_next(struct hdr_iter* iter)
  609. {
  610. iter->counts_index++;
  611. if (!has_buckets(iter))
  612. {
  613. return false;
  614. }
  615. iter->count = counts_get_normalised(iter->h, iter->counts_index);
  616. iter->cumulative_count += iter->count;
  617. iter->value = hdr_value_at_index(iter->h, iter->counts_index);
  618. iter->highest_equivalent_value = highest_equivalent_value(iter->h, iter->value);
  619. iter->lowest_equivalent_value = lowest_equivalent_value(iter->h, iter->value);
  620. iter->median_equivalent_value = hdr_median_equivalent_value(iter->h, iter->value);
  621. return true;
  622. }
  623. static int64_t peek_next_value_from_index(struct hdr_iter* iter)
  624. {
  625. return hdr_value_at_index(iter->h, iter->counts_index + 1);
  626. }
  627. static bool next_value_greater_than_reporting_level_upper_bound(
  628. struct hdr_iter *iter, int64_t reporting_level_upper_bound)
  629. {
  630. if (iter->counts_index >= iter->h->counts_len)
  631. {
  632. return false;
  633. }
  634. return peek_next_value_from_index(iter) > reporting_level_upper_bound;
  635. }
  636. static bool basic_iter_next(struct hdr_iter *iter)
  637. {
  638. if (!has_next(iter) || iter->counts_index >= iter->h->counts_len)
  639. {
  640. return false;
  641. }
  642. move_next(iter);
  643. return true;
  644. }
  645. static void update_iterated_values(struct hdr_iter* iter, int64_t new_value_iterated_to)
  646. {
  647. iter->value_iterated_from = iter->value_iterated_to;
  648. iter->value_iterated_to = new_value_iterated_to;
  649. }
  650. static bool all_values_iter_next(struct hdr_iter* iter)
  651. {
  652. bool result = move_next(iter);
  653. if (result)
  654. {
  655. update_iterated_values(iter, iter->value);
  656. }
  657. return result;
  658. }
  659. void hdr_iter_init(struct hdr_iter* iter, const struct hdr_histogram* h)
  660. {
  661. iter->h = h;
  662. iter->counts_index = -1;
  663. iter->total_count = h->total_count;
  664. iter->count = 0;
  665. iter->cumulative_count = 0;
  666. iter->value = 0;
  667. iter->highest_equivalent_value = 0;
  668. iter->value_iterated_from = 0;
  669. iter->value_iterated_to = 0;
  670. iter->_next_fp = all_values_iter_next;
  671. }
  672. bool hdr_iter_next(struct hdr_iter* iter)
  673. {
  674. return iter->_next_fp(iter);
  675. }
  676. /* ######## ######## ######## ###### ######## ## ## ######## #### ## ######## ###### */
  677. /* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## */
  678. /* ## ## ## ## ## ## ## #### ## ## ## ## ## ## */
  679. /* ######## ###### ######## ## ###### ## ## ## ## ## ## ###### ###### */
  680. /* ## ## ## ## ## ## ## #### ## ## ## ## ## */
  681. /* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## */
  682. /* ## ######## ## ## ###### ######## ## ## ## #### ######## ######## ###### */
  683. static bool percentile_iter_next(struct hdr_iter* iter)
  684. {
  685. int64_t temp, half_distance, percentile_reporting_ticks;
  686. struct hdr_iter_percentiles* percentiles = &iter->specifics.percentiles;
  687. if (!has_next(iter))
  688. {
  689. if (percentiles->seen_last_value)
  690. {
  691. return false;
  692. }
  693. percentiles->seen_last_value = true;
  694. percentiles->percentile = 100.0;
  695. return true;
  696. }
  697. if (iter->counts_index == -1 && !basic_iter_next(iter))
  698. {
  699. return false;
  700. }
  701. do
  702. {
  703. double current_percentile = (100.0 * (double) iter->cumulative_count) / iter->h->total_count;
  704. if (iter->count != 0 &&
  705. percentiles->percentile_to_iterate_to <= current_percentile)
  706. {
  707. update_iterated_values(iter, highest_equivalent_value(iter->h, iter->value));
  708. percentiles->percentile = percentiles->percentile_to_iterate_to;
  709. temp = (int64_t)(log(100 / (100.0 - (percentiles->percentile_to_iterate_to))) / log(2)) + 1;
  710. half_distance = (int64_t) pow(2, (double) temp);
  711. percentile_reporting_ticks = percentiles->ticks_per_half_distance * half_distance;
  712. percentiles->percentile_to_iterate_to += 100.0 / percentile_reporting_ticks;
  713. return true;
  714. }
  715. }
  716. while (basic_iter_next(iter));
  717. return true;
  718. }
  719. void hdr_iter_percentile_init(struct hdr_iter* iter, const struct hdr_histogram* h, int32_t ticks_per_half_distance)
  720. {
  721. iter->h = h;
  722. hdr_iter_init(iter, h);
  723. iter->specifics.percentiles.seen_last_value = false;
  724. iter->specifics.percentiles.ticks_per_half_distance = ticks_per_half_distance;
  725. iter->specifics.percentiles.percentile_to_iterate_to = 0.0;
  726. iter->specifics.percentiles.percentile = 0.0;
  727. iter->_next_fp = percentile_iter_next;
  728. }
  729. static void format_line_string(char* str, size_t len, int significant_figures, format_type format)
  730. {
  731. #if defined(_MSC_VER)
  732. #define snprintf _snprintf
  733. #pragma warning(push)
  734. #pragma warning(disable: 4996)
  735. #endif
  736. const char* format_str = "%s%d%s";
  737. switch (format)
  738. {
  739. case CSV:
  740. snprintf(str, len, format_str, "%.", significant_figures, "f,%f,%d,%.2f\n");
  741. break;
  742. case CLASSIC:
  743. snprintf(str, len, format_str, "%12.", significant_figures, "f %12f %12d %12.2f\n");
  744. break;
  745. default:
  746. snprintf(str, len, format_str, "%12.", significant_figures, "f %12f %12d %12.2f\n");
  747. }
  748. #if defined(_MSC_VER)
  749. #undef snprintf
  750. #pragma warning(pop)
  751. #endif
  752. }
  753. /* ######## ######## ###### ####### ######## ######## ######## ######## */
  754. /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
  755. /* ## ## ## ## ## ## ## ## ## ## ## ## ## */
  756. /* ######## ###### ## ## ## ######## ## ## ###### ## ## */
  757. /* ## ## ## ## ## ## ## ## ## ## ## ## ## */
  758. /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
  759. /* ## ## ######## ###### ####### ## ## ######## ######## ######## */
  760. static bool recorded_iter_next(struct hdr_iter* iter)
  761. {
  762. while (basic_iter_next(iter))
  763. {
  764. if (iter->count != 0)
  765. {
  766. update_iterated_values(iter, iter->value);
  767. iter->specifics.recorded.count_added_in_this_iteration_step = iter->count;
  768. return true;
  769. }
  770. }
  771. return false;
  772. }
  773. void hdr_iter_recorded_init(struct hdr_iter* iter, const struct hdr_histogram* h)
  774. {
  775. hdr_iter_init(iter, h);
  776. iter->specifics.recorded.count_added_in_this_iteration_step = 0;
  777. iter->_next_fp = recorded_iter_next;
  778. }
  779. /* ## #### ## ## ######## ### ######## */
  780. /* ## ## ### ## ## ## ## ## ## */
  781. /* ## ## #### ## ## ## ## ## ## */
  782. /* ## ## ## ## ## ###### ## ## ######## */
  783. /* ## ## ## #### ## ######### ## ## */
  784. /* ## ## ## ### ## ## ## ## ## */
  785. /* ######## #### ## ## ######## ## ## ## ## */
  786. static bool iter_linear_next(struct hdr_iter* iter)
  787. {
  788. struct hdr_iter_linear* linear = &iter->specifics.linear;
  789. linear->count_added_in_this_iteration_step = 0;
  790. if (has_next(iter) ||
  791. next_value_greater_than_reporting_level_upper_bound(
  792. iter, linear->next_value_reporting_level_lowest_equivalent))
  793. {
  794. do
  795. {
  796. if (iter->value >= linear->next_value_reporting_level_lowest_equivalent)
  797. {
  798. update_iterated_values(iter, linear->next_value_reporting_level);
  799. linear->next_value_reporting_level += linear->value_units_per_bucket;
  800. linear->next_value_reporting_level_lowest_equivalent =
  801. lowest_equivalent_value(iter->h, linear->next_value_reporting_level);
  802. return true;
  803. }
  804. if (!move_next(iter))
  805. {
  806. return true;
  807. }
  808. linear->count_added_in_this_iteration_step += iter->count;
  809. }
  810. while (true);
  811. }
  812. return false;
  813. }
  814. void hdr_iter_linear_init(struct hdr_iter* iter, const struct hdr_histogram* h, int64_t value_units_per_bucket)
  815. {
  816. hdr_iter_init(iter, h);
  817. iter->specifics.linear.count_added_in_this_iteration_step = 0;
  818. iter->specifics.linear.value_units_per_bucket = value_units_per_bucket;
  819. iter->specifics.linear.next_value_reporting_level = value_units_per_bucket;
  820. iter->specifics.linear.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_per_bucket);
  821. iter->_next_fp = iter_linear_next;
  822. }
  823. void hdr_iter_linear_set_value_units_per_bucket(struct hdr_iter* iter, int64_t value_units_per_bucket)
  824. {
  825. iter->specifics.linear.value_units_per_bucket = value_units_per_bucket;
  826. }
  827. /* ## ####### ###### ### ######## #### ######## ## ## ## ## #### ###### */
  828. /* ## ## ## ## ## ## ## ## ## ## ## ## ## ### ### ## ## ## */
  829. /* ## ## ## ## ## ## ## ## ## ## ## ## #### #### ## ## */
  830. /* ## ## ## ## #### ## ## ######## ## ## ######### ## ### ## ## ## */
  831. /* ## ## ## ## ## ######### ## ## ## ## ## ## ## ## ## ## */
  832. /* ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
  833. /* ######## ####### ###### ## ## ## ## #### ## ## ## ## ## #### ###### */
  834. static bool log_iter_next(struct hdr_iter *iter)
  835. {
  836. struct hdr_iter_log* logarithmic = &iter->specifics.log;
  837. logarithmic->count_added_in_this_iteration_step = 0;
  838. if (has_next(iter) ||
  839. next_value_greater_than_reporting_level_upper_bound(
  840. iter, logarithmic->next_value_reporting_level_lowest_equivalent))
  841. {
  842. do
  843. {
  844. if (iter->value >= logarithmic->next_value_reporting_level_lowest_equivalent)
  845. {
  846. update_iterated_values(iter, logarithmic->next_value_reporting_level);
  847. logarithmic->next_value_reporting_level *= (int64_t)logarithmic->log_base;
  848. logarithmic->next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(iter->h, logarithmic->next_value_reporting_level);
  849. return true;
  850. }
  851. if (!move_next(iter))
  852. {
  853. return true;
  854. }
  855. logarithmic->count_added_in_this_iteration_step += iter->count;
  856. }
  857. while (true);
  858. }
  859. return false;
  860. }
  861. void hdr_iter_log_init(
  862. struct hdr_iter* iter,
  863. const struct hdr_histogram* h,
  864. int64_t value_units_first_bucket,
  865. double log_base)
  866. {
  867. hdr_iter_init(iter, h);
  868. iter->specifics.log.count_added_in_this_iteration_step = 0;
  869. iter->specifics.log.log_base = log_base;
  870. iter->specifics.log.next_value_reporting_level = value_units_first_bucket;
  871. iter->specifics.log.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_first_bucket);
  872. iter->_next_fp = log_iter_next;
  873. }
  874. /* Printing. */
  875. static const char* format_head_string(format_type format)
  876. {
  877. switch (format)
  878. {
  879. case CSV:
  880. return "%s,%s,%s,%s\n";
  881. case CLASSIC:
  882. default:
  883. return "%12s %12s %12s %12s\n\n";
  884. }
  885. }
  886. static const char CLASSIC_FOOTER[] =
  887. "#[Mean = %12.3f, StdDeviation = %12.3f]\n"
  888. "#[Max = %12.3f, Total count = %12" PRIu64 "]\n"
  889. "#[Buckets = %12d, SubBuckets = %12d]\n";
  890. int hdr_percentiles_print(
  891. struct hdr_histogram* h, FILE* stream, int32_t ticks_per_half_distance,
  892. double value_scale, format_type format)
  893. {
  894. char line_format[25];
  895. const char* head_format;
  896. int rc = 0;
  897. struct hdr_iter iter;
  898. struct hdr_iter_percentiles * percentiles;
  899. format_line_string(line_format, 25, h->significant_figures, format);
  900. head_format = format_head_string(format);
  901. hdr_iter_percentile_init(&iter, h, ticks_per_half_distance);
  902. if (fprintf(
  903. stream, head_format,
  904. "Value", "Percentile", "TotalCount", "1/(1-Percentile)") < 0)
  905. {
  906. rc = EIO;
  907. goto cleanup;
  908. }
  909. percentiles = &iter.specifics.percentiles;
  910. while (hdr_iter_next(&iter))
  911. {
  912. double value = iter.highest_equivalent_value / value_scale;
  913. double percentile = percentiles->percentile / 100.0;
  914. int64_t total_count = iter.cumulative_count;
  915. double inverted_percentile = (1.0 / (1.0 - percentile));
  916. if (fprintf(
  917. stream, line_format, value, percentile, total_count, inverted_percentile) < 0)
  918. {
  919. rc = EIO;
  920. goto cleanup;
  921. }
  922. }
  923. if (CLASSIC == format)
  924. {
  925. double mean = hdr_mean(h) / value_scale;
  926. double stddev = hdr_stddev(h) / value_scale;
  927. double max = hdr_max(h) / value_scale;
  928. if (fprintf(
  929. stream, CLASSIC_FOOTER, mean, stddev, max,
  930. h->total_count, h->bucket_count, h->sub_bucket_count) < 0)
  931. {
  932. rc = EIO;
  933. goto cleanup;
  934. }
  935. }
  936. cleanup:
  937. return rc;
  938. }