couchbase 3.1.1-universal-darwin-20 → 3.2.0-universal-darwin-20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/CMakeLists.txt +3 -1
- data/ext/build_version.hxx.in +1 -1
- data/ext/cmake/Testing.cmake +1 -0
- data/ext/cmake/ThirdPartyDependencies.cmake +6 -0
- data/ext/cmake/VersionInfo.cmake +3 -0
- data/ext/couchbase/bucket.hxx +47 -28
- data/ext/couchbase/cbsasl/client.h +1 -1
- data/ext/couchbase/cbsasl/context.cc +1 -1
- data/ext/couchbase/cbsasl/context.h +3 -3
- data/ext/couchbase/cbsasl/mechanism.cc +5 -8
- data/ext/couchbase/cbsasl/mechanism.h +1 -4
- data/ext/couchbase/cbsasl/plain/plain.cc +1 -1
- data/ext/couchbase/cbsasl/scram-sha/scram-sha.cc +30 -36
- data/ext/couchbase/cluster.hxx +40 -22
- data/ext/couchbase/cluster_options.hxx +7 -1
- data/ext/couchbase/configuration.hxx +37 -16
- data/ext/couchbase/couchbase.cxx +1145 -291
- data/ext/couchbase/error_map.hxx +1 -1
- data/ext/couchbase/errors.hxx +25 -17
- data/ext/couchbase/io/dns_client.hxx +3 -3
- data/ext/couchbase/io/dns_codec.hxx +4 -5
- data/ext/couchbase/io/dns_config.hxx +5 -6
- data/ext/couchbase/io/dns_message.hxx +3 -3
- data/ext/couchbase/io/http_command.hxx +70 -35
- data/ext/couchbase/io/http_session.hxx +4 -3
- data/ext/couchbase/io/http_session_manager.hxx +28 -19
- data/ext/couchbase/io/mcbp_command.hxx +51 -19
- data/ext/couchbase/io/mcbp_context.hxx +1 -1
- data/ext/couchbase/io/mcbp_parser.hxx +4 -4
- data/ext/couchbase/io/mcbp_session.hxx +91 -101
- data/ext/couchbase/io/query_cache.hxx +2 -2
- data/ext/couchbase/io/retry_orchestrator.hxx +2 -4
- data/ext/couchbase/io/retry_reason.hxx +2 -2
- data/ext/couchbase/io/retry_strategy.hxx +1 -6
- data/ext/couchbase/io/streams.hxx +7 -7
- data/ext/couchbase/metrics/logging_meter.hxx +228 -0
- data/ext/couchbase/metrics/logging_meter_options.hxx +28 -0
- data/ext/couchbase/metrics/meter.hxx +49 -0
- data/ext/couchbase/metrics/noop_meter.hxx +43 -0
- data/ext/couchbase/operations.hxx +4 -0
- data/ext/couchbase/operations/analytics_dataset_create.hxx +16 -12
- data/ext/couchbase/operations/analytics_dataset_drop.hxx +11 -11
- data/ext/couchbase/operations/analytics_dataset_get_all.hxx +6 -6
- data/ext/couchbase/operations/analytics_dataverse_create.hxx +10 -11
- data/ext/couchbase/operations/analytics_dataverse_drop.hxx +10 -11
- data/ext/couchbase/operations/analytics_get_pending_mutations.hxx +9 -11
- data/ext/couchbase/operations/analytics_index_create.hxx +14 -13
- data/ext/couchbase/operations/analytics_index_drop.hxx +18 -12
- data/ext/couchbase/operations/analytics_index_get_all.hxx +8 -6
- data/ext/couchbase/operations/analytics_link.hxx +39 -0
- data/ext/couchbase/operations/analytics_link_azure_blob_external.hxx +145 -0
- data/ext/couchbase/operations/analytics_link_connect.hxx +14 -12
- data/ext/couchbase/operations/analytics_link_couchbase_remote.hxx +220 -0
- data/ext/couchbase/operations/analytics_link_create.hxx +128 -0
- data/ext/couchbase/operations/analytics_link_disconnect.hxx +11 -12
- data/ext/couchbase/operations/analytics_link_drop.hxx +130 -0
- data/ext/couchbase/operations/analytics_link_get_all.hxx +160 -0
- data/ext/couchbase/operations/analytics_link_replace.hxx +128 -0
- data/ext/couchbase/operations/analytics_link_s3_external.hxx +122 -0
- data/ext/couchbase/operations/bucket_create.hxx +8 -8
- data/ext/couchbase/operations/bucket_drop.hxx +5 -5
- data/ext/couchbase/operations/bucket_flush.hxx +5 -5
- data/ext/couchbase/operations/bucket_get.hxx +7 -7
- data/ext/couchbase/operations/bucket_get_all.hxx +7 -5
- data/ext/couchbase/operations/bucket_settings.hxx +40 -49
- data/ext/couchbase/operations/bucket_update.hxx +8 -8
- data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +7 -7
- data/ext/couchbase/operations/collection_create.hxx +11 -11
- data/ext/couchbase/operations/collection_drop.hxx +12 -10
- data/ext/couchbase/operations/collections_manifest_get.hxx +3 -3
- data/ext/couchbase/operations/design_document.hxx +2 -2
- data/ext/couchbase/operations/document_analytics.hxx +29 -36
- data/ext/couchbase/operations/document_append.hxx +3 -3
- data/ext/couchbase/operations/document_decrement.hxx +3 -3
- data/ext/couchbase/operations/document_exists.hxx +2 -2
- data/ext/couchbase/operations/document_get.hxx +3 -3
- data/ext/couchbase/operations/document_get_and_lock.hxx +5 -3
- data/ext/couchbase/operations/document_get_and_touch.hxx +5 -3
- data/ext/couchbase/operations/document_get_projected.hxx +10 -11
- data/ext/couchbase/operations/document_increment.hxx +3 -3
- data/ext/couchbase/operations/document_insert.hxx +3 -3
- data/ext/couchbase/operations/document_lookup_in.hxx +12 -18
- data/ext/couchbase/operations/document_mutate_in.hxx +13 -18
- data/ext/couchbase/operations/document_prepend.hxx +3 -3
- data/ext/couchbase/operations/document_query.hxx +39 -41
- data/ext/couchbase/operations/document_remove.hxx +3 -3
- data/ext/couchbase/operations/document_replace.hxx +3 -3
- data/ext/couchbase/operations/document_search.hxx +56 -61
- data/ext/couchbase/operations/document_touch.hxx +3 -3
- data/ext/couchbase/operations/document_unlock.hxx +3 -3
- data/ext/couchbase/operations/document_upsert.hxx +3 -3
- data/ext/couchbase/operations/document_view.hxx +23 -23
- data/ext/couchbase/operations/group_drop.hxx +5 -5
- data/ext/couchbase/operations/group_get.hxx +7 -7
- data/ext/couchbase/operations/group_get_all.hxx +6 -6
- data/ext/couchbase/operations/group_upsert.hxx +11 -11
- data/ext/couchbase/operations/http_noop.hxx +6 -6
- data/ext/couchbase/operations/mcbp_noop.hxx +3 -3
- data/ext/couchbase/operations/query_index_build_deferred.hxx +6 -6
- data/ext/couchbase/operations/query_index_create.hxx +10 -8
- data/ext/couchbase/operations/query_index_drop.hxx +8 -8
- data/ext/couchbase/operations/query_index_get_all.hxx +43 -39
- data/ext/couchbase/operations/rbac.hxx +40 -63
- data/ext/couchbase/operations/role_get_all.hxx +6 -6
- data/ext/couchbase/operations/scope_create.hxx +10 -10
- data/ext/couchbase/operations/scope_drop.hxx +9 -9
- data/ext/couchbase/operations/scope_get_all.hxx +8 -8
- data/ext/couchbase/operations/search_get_stats.hxx +5 -3
- data/ext/couchbase/operations/search_index.hxx +6 -15
- data/ext/couchbase/operations/search_index_analyze_document.hxx +11 -11
- data/ext/couchbase/operations/search_index_control_ingest.hxx +9 -9
- data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +9 -9
- data/ext/couchbase/operations/search_index_control_query.hxx +9 -9
- data/ext/couchbase/operations/search_index_drop.hxx +11 -9
- data/ext/couchbase/operations/search_index_get.hxx +11 -9
- data/ext/couchbase/operations/search_index_get_all.hxx +11 -11
- data/ext/couchbase/operations/search_index_get_documents_count.hxx +10 -10
- data/ext/couchbase/operations/search_index_get_stats.hxx +10 -8
- data/ext/couchbase/operations/search_index_upsert.hxx +12 -10
- data/ext/couchbase/operations/user_drop.hxx +5 -5
- data/ext/couchbase/operations/user_get.hxx +7 -7
- data/ext/couchbase/operations/user_get_all.hxx +6 -6
- data/ext/couchbase/operations/user_upsert.hxx +9 -9
- data/ext/couchbase/operations/view_index_drop.hxx +10 -10
- data/ext/couchbase/operations/view_index_get.hxx +13 -15
- data/ext/couchbase/operations/view_index_get_all.hxx +17 -20
- data/ext/couchbase/operations/view_index_upsert.hxx +9 -7
- data/ext/couchbase/origin.hxx +14 -10
- data/ext/couchbase/platform/backtrace.c +1 -1
- data/ext/couchbase/platform/base64.cc +5 -5
- data/ext/couchbase/platform/base64.h +2 -5
- data/ext/couchbase/protocol/client_opcode.hxx +7 -4
- data/ext/couchbase/protocol/client_request.hxx +2 -2
- data/ext/couchbase/protocol/client_response.hxx +41 -16
- data/ext/couchbase/protocol/cmd_append.hxx +17 -16
- data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +4 -4
- data/ext/couchbase/protocol/cmd_decrement.hxx +10 -11
- data/ext/couchbase/protocol/cmd_exists.hxx +12 -15
- data/ext/couchbase/protocol/cmd_get.hxx +11 -14
- data/ext/couchbase/protocol/cmd_get_and_lock.hxx +10 -12
- data/ext/couchbase/protocol/cmd_get_and_touch.hxx +10 -12
- data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +13 -18
- data/ext/couchbase/protocol/cmd_get_collection_id.hxx +12 -15
- data/ext/couchbase/protocol/cmd_get_collections_manifest.hxx +12 -16
- data/ext/couchbase/protocol/cmd_get_error_map.hxx +14 -17
- data/ext/couchbase/protocol/cmd_hello.hxx +8 -10
- data/ext/couchbase/protocol/cmd_increment.hxx +9 -10
- data/ext/couchbase/protocol/cmd_insert.hxx +9 -9
- data/ext/couchbase/protocol/cmd_lookup_in.hxx +12 -13
- data/ext/couchbase/protocol/cmd_mutate_in.hxx +11 -11
- data/ext/couchbase/protocol/cmd_noop.hxx +16 -20
- data/ext/couchbase/protocol/cmd_prepend.hxx +9 -10
- data/ext/couchbase/protocol/cmd_remove.hxx +10 -13
- data/ext/couchbase/protocol/cmd_replace.hxx +7 -7
- data/ext/couchbase/protocol/cmd_sasl_auth.hxx +8 -10
- data/ext/couchbase/protocol/cmd_sasl_list_mechs.hxx +10 -15
- data/ext/couchbase/protocol/cmd_sasl_step.hxx +10 -12
- data/ext/couchbase/protocol/cmd_select_bucket.hxx +14 -18
- data/ext/couchbase/protocol/cmd_touch.hxx +8 -11
- data/ext/couchbase/protocol/cmd_unlock.hxx +10 -14
- data/ext/couchbase/protocol/cmd_upsert.hxx +8 -8
- data/ext/couchbase/protocol/datatype.hxx +3 -3
- data/ext/couchbase/protocol/durability_level.hxx +2 -2
- data/ext/couchbase/protocol/frame_info_id.hxx +4 -4
- data/ext/couchbase/protocol/hello_feature.hxx +2 -2
- data/ext/couchbase/protocol/magic.hxx +2 -2
- data/ext/couchbase/protocol/server_opcode.hxx +2 -2
- data/ext/couchbase/protocol/server_request.hxx +1 -1
- data/ext/couchbase/protocol/status.hxx +4 -7
- data/ext/couchbase/protocol/unsigned_leb128.h +5 -20
- data/ext/couchbase/service_type.hxx +4 -4
- data/ext/couchbase/tracing/constants.hxx +261 -0
- data/ext/couchbase/tracing/noop_tracer.hxx +50 -0
- data/ext/couchbase/tracing/request_tracer.hxx +77 -0
- data/ext/couchbase/tracing/threshold_logging_options.hxx +64 -0
- data/ext/couchbase/tracing/threshold_logging_tracer.hxx +366 -0
- data/ext/couchbase/utils/byteswap.hxx +1 -1
- data/ext/couchbase/utils/connection_string.hxx +21 -1
- data/ext/couchbase/utils/name_codec.hxx +41 -0
- data/ext/couchbase/utils/url_codec.hxx +236 -0
- data/ext/couchbase/version.hxx +1 -1
- data/ext/test/CMakeLists.txt +1 -0
- data/ext/test/test_native_trivial_query.cxx +60 -0
- data/ext/third_party/hdr_histogram_c/CMakeLists.txt +84 -0
- data/ext/third_party/hdr_histogram_c/COPYING.txt +121 -0
- data/ext/third_party/hdr_histogram_c/LICENSE.txt +41 -0
- data/ext/third_party/hdr_histogram_c/config.cmake.in +6 -0
- data/ext/third_party/hdr_histogram_c/src/CMakeLists.txt +83 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_atomic.h +146 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_encoding.c +322 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_encoding.h +79 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_endian.h +116 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_histogram.c +1196 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_histogram.h +516 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.c +1290 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log.h +236 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_histogram_log_no_op.c +171 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.c +227 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_interval_recorder.h +109 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_malloc.h +19 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_tests.h +22 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_thread.c +108 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_thread.h +55 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_time.c +98 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_time.h +49 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.c +143 -0
- data/ext/third_party/hdr_histogram_c/src/hdr_writer_reader_phaser.h +51 -0
- data/lib/couchbase/cluster.rb +1 -0
- data/lib/couchbase/errors.rb +3 -0
- data/lib/couchbase/libcouchbase.bundle +0 -0
- data/lib/couchbase/management/analytics_index_manager.rb +920 -226
- data/lib/couchbase/management/bucket_manager.rb +207 -69
- data/lib/couchbase/management/collection_manager.rb +173 -61
- data/lib/couchbase/management/query_index_manager.rb +357 -169
- data/lib/couchbase/options.rb +75 -3
- data/lib/couchbase/scope.rb +102 -0
- data/lib/couchbase/utils/time.rb +4 -0
- data/lib/couchbase/version.rb +6 -6
- metadata +48 -5
@@ -0,0 +1,79 @@
|
|
1
|
+
/**
|
2
|
+
* hdr_encoding.h
|
3
|
+
* Written by Michael Barker and released to the public domain,
|
4
|
+
* as explained at http://creativecommons.org/publicdomain/zero/1.0/
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef HDR_ENCODING_H
|
8
|
+
#define HDR_ENCODING_H
|
9
|
+
|
10
|
+
#include <stdint.h>
|
11
|
+
|
12
|
+
#define MAX_BYTES_LEB128 9
|
13
|
+
|
14
|
+
#ifdef __cplusplus
|
15
|
+
extern "C" {
|
16
|
+
#endif
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Writes a int64_t value to the given buffer in LEB128 ZigZag encoded format
|
20
|
+
*
|
21
|
+
* @param buffer the buffer to write to
|
22
|
+
* @param signed_value the value to write to the buffer
|
23
|
+
* @return the number of bytes written to the buffer
|
24
|
+
*/
|
25
|
+
int zig_zag_encode_i64(uint8_t* buffer, int64_t signed_value);
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Read an LEB128 ZigZag encoded long value from the given buffer
|
29
|
+
*
|
30
|
+
* @param buffer the buffer to read from
|
31
|
+
* @param retVal out value to capture the read value
|
32
|
+
* @return the number of bytes read from the buffer
|
33
|
+
*/
|
34
|
+
int zig_zag_decode_i64(const uint8_t* buffer, int64_t* signed_value);
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Gets the length in bytes of base64 data, given the input size.
|
38
|
+
*
|
39
|
+
* @param decoded_size the size of the unencoded values.
|
40
|
+
* @return the encoded size
|
41
|
+
*/
|
42
|
+
size_t hdr_base64_encoded_len(size_t decoded_size);
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Encode into base64.
|
46
|
+
*
|
47
|
+
* @param input the data to encode
|
48
|
+
* @param input_len the length of the data to encode
|
49
|
+
* @param output the buffer to write the output to
|
50
|
+
* @param output_len the number of bytes to write to the output
|
51
|
+
*/
|
52
|
+
int hdr_base64_encode(
|
53
|
+
const uint8_t* input, size_t input_len, char* output, size_t output_len);
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Gets the length in bytes of decoded base64 data, given the size of the base64 encoded
|
57
|
+
* data.
|
58
|
+
*
|
59
|
+
* @param encoded_size the size of the encoded value.
|
60
|
+
* @return the decoded size
|
61
|
+
*/
|
62
|
+
size_t hdr_base64_decoded_len(size_t encoded_size);
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Decode from base64.
|
66
|
+
*
|
67
|
+
* @param input the base64 encoded data
|
68
|
+
* @param input_len the size in bytes of the endcoded data
|
69
|
+
* @param output the buffer to write the decoded data to
|
70
|
+
* @param output_len the number of bytes to write to the output data
|
71
|
+
*/
|
72
|
+
int hdr_base64_decode(
|
73
|
+
const char* input, size_t input_len, uint8_t* output, size_t output_len);
|
74
|
+
|
75
|
+
#ifdef __cplusplus
|
76
|
+
}
|
77
|
+
#endif
|
78
|
+
|
79
|
+
#endif /* HDR_HISTOGRAM_HDR_ENCODING_H */
|
@@ -0,0 +1,116 @@
|
|
1
|
+
/**
|
2
|
+
* hdr_time.h
|
3
|
+
* Released to the public domain, as explained at http://creativecommons.org/publicdomain/zero/1.0/
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef HDR_ENDIAN_H__
|
7
|
+
#define HDR_ENDIAN_H__
|
8
|
+
|
9
|
+
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
|
10
|
+
|
11
|
+
# define __WINDOWS__
|
12
|
+
|
13
|
+
#endif
|
14
|
+
|
15
|
+
#if defined(__linux__) || defined(__CYGWIN__)
|
16
|
+
|
17
|
+
# include <endian.h>
|
18
|
+
|
19
|
+
#elif defined(__APPLE__)
|
20
|
+
|
21
|
+
# include <libkern/OSByteOrder.h>
|
22
|
+
|
23
|
+
# define htobe16(x) OSSwapHostToBigInt16(x)
|
24
|
+
# define htole16(x) OSSwapHostToLittleInt16(x)
|
25
|
+
# define be16toh(x) OSSwapBigToHostInt16(x)
|
26
|
+
# define le16toh(x) OSSwapLittleToHostInt16(x)
|
27
|
+
|
28
|
+
# define htobe32(x) OSSwapHostToBigInt32(x)
|
29
|
+
# define htole32(x) OSSwapHostToLittleInt32(x)
|
30
|
+
# define be32toh(x) OSSwapBigToHostInt32(x)
|
31
|
+
# define le32toh(x) OSSwapLittleToHostInt32(x)
|
32
|
+
|
33
|
+
# define htobe64(x) OSSwapHostToBigInt64(x)
|
34
|
+
# define htole64(x) OSSwapHostToLittleInt64(x)
|
35
|
+
# define be64toh(x) OSSwapBigToHostInt64(x)
|
36
|
+
# define le64toh(x) OSSwapLittleToHostInt64(x)
|
37
|
+
|
38
|
+
# define __BYTE_ORDER BYTE_ORDER
|
39
|
+
# define __BIG_ENDIAN BIG_ENDIAN
|
40
|
+
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
41
|
+
# define __PDP_ENDIAN PDP_ENDIAN
|
42
|
+
|
43
|
+
#elif defined(__OpenBSD__)
|
44
|
+
|
45
|
+
# include <sys/endian.h>
|
46
|
+
|
47
|
+
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
48
|
+
|
49
|
+
# include <sys/endian.h>
|
50
|
+
|
51
|
+
# define be16toh(x) betoh16(x)
|
52
|
+
# define le16toh(x) letoh16(x)
|
53
|
+
|
54
|
+
# define be32toh(x) betoh32(x)
|
55
|
+
# define le32toh(x) letoh32(x)
|
56
|
+
|
57
|
+
# define be64toh(x) betoh64(x)
|
58
|
+
# define le64toh(x) letoh64(x)
|
59
|
+
|
60
|
+
#elif defined(__WINDOWS__)
|
61
|
+
|
62
|
+
# include <winsock2.h>
|
63
|
+
|
64
|
+
# if BYTE_ORDER == LITTLE_ENDIAN
|
65
|
+
|
66
|
+
# define htobe16(x) htons(x)
|
67
|
+
# define htole16(x) (x)
|
68
|
+
# define be16toh(x) ntohs(x)
|
69
|
+
# define le16toh(x) (x)
|
70
|
+
|
71
|
+
# define htobe32(x) htonl(x)
|
72
|
+
# define htole32(x) (x)
|
73
|
+
# define be32toh(x) ntohl(x)
|
74
|
+
# define le32toh(x) (x)
|
75
|
+
|
76
|
+
# define htobe64(x) htonll(x)
|
77
|
+
# define htole64(x) (x)
|
78
|
+
# define be64toh(x) ntohll(x)
|
79
|
+
# define le64toh(x) (x)
|
80
|
+
|
81
|
+
# elif BYTE_ORDER == BIG_ENDIAN
|
82
|
+
|
83
|
+
/* that would be xbox 360 */
|
84
|
+
# define htobe16(x) (x)
|
85
|
+
# define htole16(x) __builtin_bswap16(x)
|
86
|
+
# define be16toh(x) (x)
|
87
|
+
# define le16toh(x) __builtin_bswap16(x)
|
88
|
+
|
89
|
+
# define htobe32(x) (x)
|
90
|
+
# define htole32(x) __builtin_bswap32(x)
|
91
|
+
# define be32toh(x) (x)
|
92
|
+
# define le32toh(x) __builtin_bswap32(x)
|
93
|
+
|
94
|
+
# define htobe64(x) (x)
|
95
|
+
# define htole64(x) __builtin_bswap64(x)
|
96
|
+
# define be64toh(x) (x)
|
97
|
+
# define le64toh(x) __builtin_bswap64(x)
|
98
|
+
|
99
|
+
# else
|
100
|
+
|
101
|
+
# error byte order not supported
|
102
|
+
|
103
|
+
# endif
|
104
|
+
|
105
|
+
# define __BYTE_ORDER BYTE_ORDER
|
106
|
+
# define __BIG_ENDIAN BIG_ENDIAN
|
107
|
+
# define __LITTLE_ENDIAN LITTLE_ENDIAN
|
108
|
+
# define __PDP_ENDIAN PDP_ENDIAN
|
109
|
+
|
110
|
+
#else
|
111
|
+
|
112
|
+
# error platform not supported
|
113
|
+
|
114
|
+
#endif
|
115
|
+
|
116
|
+
#endif
|
@@ -0,0 +1,1196 @@
|
|
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
|
+
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <stdbool.h>
|
9
|
+
#include <math.h>
|
10
|
+
#include <stdio.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <stdint.h>
|
13
|
+
#include <errno.h>
|
14
|
+
#include <inttypes.h>
|
15
|
+
|
16
|
+
#include "hdr_histogram.h"
|
17
|
+
#include "hdr_tests.h"
|
18
|
+
#include "hdr_atomic.h"
|
19
|
+
|
20
|
+
#ifndef HDR_MALLOC_INCLUDE
|
21
|
+
#define HDR_MALLOC_INCLUDE "hdr_malloc.h"
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#include HDR_MALLOC_INCLUDE
|
25
|
+
|
26
|
+
/* ###### ####### ## ## ## ## ######## ###### */
|
27
|
+
/* ## ## ## ## ## ## ### ## ## ## ## */
|
28
|
+
/* ## ## ## ## ## #### ## ## ## */
|
29
|
+
/* ## ## ## ## ## ## ## ## ## ###### */
|
30
|
+
/* ## ## ## ## ## ## #### ## ## */
|
31
|
+
/* ## ## ## ## ## ## ## ### ## ## ## */
|
32
|
+
/* ###### ####### ####### ## ## ## ###### */
|
33
|
+
|
34
|
+
static int32_t normalize_index(const struct hdr_histogram* h, int32_t index)
|
35
|
+
{
|
36
|
+
int32_t normalized_index;
|
37
|
+
int32_t adjustment = 0;
|
38
|
+
if (h->normalizing_index_offset == 0)
|
39
|
+
{
|
40
|
+
return index;
|
41
|
+
}
|
42
|
+
|
43
|
+
normalized_index = index - h->normalizing_index_offset;
|
44
|
+
|
45
|
+
if (normalized_index < 0)
|
46
|
+
{
|
47
|
+
adjustment = h->counts_len;
|
48
|
+
}
|
49
|
+
else if (normalized_index >= h->counts_len)
|
50
|
+
{
|
51
|
+
adjustment = -h->counts_len;
|
52
|
+
}
|
53
|
+
|
54
|
+
return normalized_index + adjustment;
|
55
|
+
}
|
56
|
+
|
57
|
+
static int64_t counts_get_direct(const struct hdr_histogram* h, int32_t index)
|
58
|
+
{
|
59
|
+
return h->counts[index];
|
60
|
+
}
|
61
|
+
|
62
|
+
static int64_t counts_get_normalised(const struct hdr_histogram* h, int32_t index)
|
63
|
+
{
|
64
|
+
return counts_get_direct(h, normalize_index(h, index));
|
65
|
+
}
|
66
|
+
|
67
|
+
static void counts_inc_normalised(
|
68
|
+
struct hdr_histogram* h, int32_t index, int64_t value)
|
69
|
+
{
|
70
|
+
int32_t normalised_index = normalize_index(h, index);
|
71
|
+
h->counts[normalised_index] += value;
|
72
|
+
h->total_count += value;
|
73
|
+
}
|
74
|
+
|
75
|
+
static void counts_inc_normalised_atomic(
|
76
|
+
struct hdr_histogram* h, int32_t index, int64_t value)
|
77
|
+
{
|
78
|
+
int32_t normalised_index = normalize_index(h, index);
|
79
|
+
|
80
|
+
hdr_atomic_add_fetch_64(&h->counts[normalised_index], value);
|
81
|
+
hdr_atomic_add_fetch_64(&h->total_count, value);
|
82
|
+
}
|
83
|
+
|
84
|
+
static void update_min_max(struct hdr_histogram* h, int64_t value)
|
85
|
+
{
|
86
|
+
h->min_value = (value < h->min_value && value != 0) ? value : h->min_value;
|
87
|
+
h->max_value = (value > h->max_value) ? value : h->max_value;
|
88
|
+
}
|
89
|
+
|
90
|
+
static void update_min_max_atomic(struct hdr_histogram* h, int64_t value)
|
91
|
+
{
|
92
|
+
int64_t current_min_value;
|
93
|
+
int64_t current_max_value;
|
94
|
+
do
|
95
|
+
{
|
96
|
+
current_min_value = hdr_atomic_load_64(&h->min_value);
|
97
|
+
|
98
|
+
if (0 == value || current_min_value <= value)
|
99
|
+
{
|
100
|
+
break;
|
101
|
+
}
|
102
|
+
}
|
103
|
+
while (!hdr_atomic_compare_exchange_64(&h->min_value, ¤t_min_value, value));
|
104
|
+
|
105
|
+
do
|
106
|
+
{
|
107
|
+
current_max_value = hdr_atomic_load_64(&h->max_value);
|
108
|
+
|
109
|
+
if (value <= current_max_value)
|
110
|
+
{
|
111
|
+
break;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
while (!hdr_atomic_compare_exchange_64(&h->max_value, ¤t_max_value, value));
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
/* ## ## ######## #### ## #### ######## ## ## */
|
119
|
+
/* ## ## ## ## ## ## ## ## ## */
|
120
|
+
/* ## ## ## ## ## ## ## #### */
|
121
|
+
/* ## ## ## ## ## ## ## ## */
|
122
|
+
/* ## ## ## ## ## ## ## ## */
|
123
|
+
/* ## ## ## ## ## ## ## ## */
|
124
|
+
/* ####### ## #### ######## #### ## ## */
|
125
|
+
|
126
|
+
static int64_t power(int64_t base, int64_t exp)
|
127
|
+
{
|
128
|
+
int64_t result = 1;
|
129
|
+
while(exp)
|
130
|
+
{
|
131
|
+
result *= base; exp--;
|
132
|
+
}
|
133
|
+
return result;
|
134
|
+
}
|
135
|
+
|
136
|
+
#if defined(_MSC_VER)
|
137
|
+
# if defined(_WIN64)
|
138
|
+
# pragma intrinsic(_BitScanReverse64)
|
139
|
+
# else
|
140
|
+
# pragma intrinsic(_BitScanReverse)
|
141
|
+
# endif
|
142
|
+
#endif
|
143
|
+
|
144
|
+
static int32_t count_leading_zeros_64(int64_t value)
|
145
|
+
{
|
146
|
+
#if defined(_MSC_VER)
|
147
|
+
uint32_t leading_zero = 0;
|
148
|
+
#if defined(_WIN64)
|
149
|
+
_BitScanReverse64(&leading_zero, value);
|
150
|
+
#else
|
151
|
+
uint32_t high = value >> 32;
|
152
|
+
if (_BitScanReverse(&leading_zero, high))
|
153
|
+
{
|
154
|
+
leading_zero += 32;
|
155
|
+
}
|
156
|
+
else
|
157
|
+
{
|
158
|
+
uint32_t low = value & 0x00000000FFFFFFFF;
|
159
|
+
_BitScanReverse(&leading_zero, low);
|
160
|
+
}
|
161
|
+
#endif
|
162
|
+
return 63 - leading_zero; /* smallest power of 2 containing value */
|
163
|
+
#else
|
164
|
+
return __builtin_clzll(value); /* smallest power of 2 containing value */
|
165
|
+
#endif
|
166
|
+
}
|
167
|
+
|
168
|
+
static int32_t get_bucket_index(const struct hdr_histogram* h, int64_t value)
|
169
|
+
{
|
170
|
+
int32_t pow2ceiling = 64 - count_leading_zeros_64(value | h->sub_bucket_mask); /* smallest power of 2 containing value */
|
171
|
+
return pow2ceiling - h->unit_magnitude - (h->sub_bucket_half_count_magnitude + 1);
|
172
|
+
}
|
173
|
+
|
174
|
+
static int32_t get_sub_bucket_index(int64_t value, int32_t bucket_index, int32_t unit_magnitude)
|
175
|
+
{
|
176
|
+
return (int32_t)(value >> (bucket_index + unit_magnitude));
|
177
|
+
}
|
178
|
+
|
179
|
+
static int32_t counts_index(const struct hdr_histogram* h, int32_t bucket_index, int32_t sub_bucket_index)
|
180
|
+
{
|
181
|
+
/* Calculate the index for the first entry in the bucket: */
|
182
|
+
/* (The following is the equivalent of ((bucket_index + 1) * subBucketHalfCount) ): */
|
183
|
+
int32_t bucket_base_index = (bucket_index + 1) << h->sub_bucket_half_count_magnitude;
|
184
|
+
/* Calculate the offset in the bucket: */
|
185
|
+
int32_t offset_in_bucket = sub_bucket_index - h->sub_bucket_half_count;
|
186
|
+
/* The following is the equivalent of ((sub_bucket_index - subBucketHalfCount) + bucketBaseIndex; */
|
187
|
+
return bucket_base_index + offset_in_bucket;
|
188
|
+
}
|
189
|
+
|
190
|
+
static int64_t value_from_index(int32_t bucket_index, int32_t sub_bucket_index, int32_t unit_magnitude)
|
191
|
+
{
|
192
|
+
return ((int64_t) sub_bucket_index) << (bucket_index + unit_magnitude);
|
193
|
+
}
|
194
|
+
|
195
|
+
int32_t counts_index_for(const struct hdr_histogram* h, int64_t value)
|
196
|
+
{
|
197
|
+
int32_t bucket_index = get_bucket_index(h, value);
|
198
|
+
int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
|
199
|
+
|
200
|
+
return counts_index(h, bucket_index, sub_bucket_index);
|
201
|
+
}
|
202
|
+
|
203
|
+
int64_t hdr_value_at_index(const struct hdr_histogram *h, int32_t index)
|
204
|
+
{
|
205
|
+
int32_t bucket_index = (index >> h->sub_bucket_half_count_magnitude) - 1;
|
206
|
+
int32_t sub_bucket_index = (index & (h->sub_bucket_half_count - 1)) + h->sub_bucket_half_count;
|
207
|
+
|
208
|
+
if (bucket_index < 0)
|
209
|
+
{
|
210
|
+
sub_bucket_index -= h->sub_bucket_half_count;
|
211
|
+
bucket_index = 0;
|
212
|
+
}
|
213
|
+
|
214
|
+
return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
|
215
|
+
}
|
216
|
+
|
217
|
+
int64_t hdr_size_of_equivalent_value_range(const struct hdr_histogram* h, int64_t value)
|
218
|
+
{
|
219
|
+
int32_t bucket_index = get_bucket_index(h, value);
|
220
|
+
int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
|
221
|
+
int32_t adjusted_bucket = (sub_bucket_index >= h->sub_bucket_count) ? (bucket_index + 1) : bucket_index;
|
222
|
+
return INT64_C(1) << (h->unit_magnitude + adjusted_bucket);
|
223
|
+
}
|
224
|
+
|
225
|
+
static int64_t lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
|
226
|
+
{
|
227
|
+
int32_t bucket_index = get_bucket_index(h, value);
|
228
|
+
int32_t sub_bucket_index = get_sub_bucket_index(value, bucket_index, h->unit_magnitude);
|
229
|
+
return value_from_index(bucket_index, sub_bucket_index, h->unit_magnitude);
|
230
|
+
}
|
231
|
+
|
232
|
+
int64_t hdr_next_non_equivalent_value(const struct hdr_histogram *h, int64_t value)
|
233
|
+
{
|
234
|
+
return lowest_equivalent_value(h, value) + hdr_size_of_equivalent_value_range(h, value);
|
235
|
+
}
|
236
|
+
|
237
|
+
static int64_t highest_equivalent_value(const struct hdr_histogram* h, int64_t value)
|
238
|
+
{
|
239
|
+
return hdr_next_non_equivalent_value(h, value) - 1;
|
240
|
+
}
|
241
|
+
|
242
|
+
int64_t hdr_median_equivalent_value(const struct hdr_histogram *h, int64_t value)
|
243
|
+
{
|
244
|
+
return lowest_equivalent_value(h, value) + (hdr_size_of_equivalent_value_range(h, value) >> 1);
|
245
|
+
}
|
246
|
+
|
247
|
+
static int64_t non_zero_min(const struct hdr_histogram* h)
|
248
|
+
{
|
249
|
+
if (INT64_MAX == h->min_value)
|
250
|
+
{
|
251
|
+
return INT64_MAX;
|
252
|
+
}
|
253
|
+
|
254
|
+
return lowest_equivalent_value(h, h->min_value);
|
255
|
+
}
|
256
|
+
|
257
|
+
void hdr_reset_internal_counters(struct hdr_histogram* h)
|
258
|
+
{
|
259
|
+
int min_non_zero_index = -1;
|
260
|
+
int max_index = -1;
|
261
|
+
int64_t observed_total_count = 0;
|
262
|
+
int i;
|
263
|
+
|
264
|
+
for (i = 0; i < h->counts_len; i++)
|
265
|
+
{
|
266
|
+
int64_t count_at_index;
|
267
|
+
|
268
|
+
if ((count_at_index = counts_get_direct(h, i)) > 0)
|
269
|
+
{
|
270
|
+
observed_total_count += count_at_index;
|
271
|
+
max_index = i;
|
272
|
+
if (min_non_zero_index == -1 && i != 0)
|
273
|
+
{
|
274
|
+
min_non_zero_index = i;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
if (max_index == -1)
|
280
|
+
{
|
281
|
+
h->max_value = 0;
|
282
|
+
}
|
283
|
+
else
|
284
|
+
{
|
285
|
+
int64_t max_value = hdr_value_at_index(h, max_index);
|
286
|
+
h->max_value = highest_equivalent_value(h, max_value);
|
287
|
+
}
|
288
|
+
|
289
|
+
if (min_non_zero_index == -1)
|
290
|
+
{
|
291
|
+
h->min_value = INT64_MAX;
|
292
|
+
}
|
293
|
+
else
|
294
|
+
{
|
295
|
+
h->min_value = hdr_value_at_index(h, min_non_zero_index);
|
296
|
+
}
|
297
|
+
|
298
|
+
h->total_count = observed_total_count;
|
299
|
+
}
|
300
|
+
|
301
|
+
static int32_t buckets_needed_to_cover_value(int64_t value, int32_t sub_bucket_count, int32_t unit_magnitude)
|
302
|
+
{
|
303
|
+
int64_t smallest_untrackable_value = ((int64_t) sub_bucket_count) << unit_magnitude;
|
304
|
+
int32_t buckets_needed = 1;
|
305
|
+
while (smallest_untrackable_value <= value)
|
306
|
+
{
|
307
|
+
if (smallest_untrackable_value > INT64_MAX / 2)
|
308
|
+
{
|
309
|
+
return buckets_needed + 1;
|
310
|
+
}
|
311
|
+
smallest_untrackable_value <<= 1;
|
312
|
+
buckets_needed++;
|
313
|
+
}
|
314
|
+
|
315
|
+
return buckets_needed;
|
316
|
+
}
|
317
|
+
|
318
|
+
/* ## ## ######## ## ## ####### ######## ## ## */
|
319
|
+
/* ### ### ## ### ### ## ## ## ## ## ## */
|
320
|
+
/* #### #### ## #### #### ## ## ## ## #### */
|
321
|
+
/* ## ### ## ###### ## ### ## ## ## ######## ## */
|
322
|
+
/* ## ## ## ## ## ## ## ## ## ## */
|
323
|
+
/* ## ## ## ## ## ## ## ## ## ## */
|
324
|
+
/* ## ## ######## ## ## ####### ## ## ## */
|
325
|
+
|
326
|
+
int hdr_calculate_bucket_config(
|
327
|
+
int64_t lowest_discernible_value,
|
328
|
+
int64_t highest_trackable_value,
|
329
|
+
int significant_figures,
|
330
|
+
struct hdr_histogram_bucket_config* cfg)
|
331
|
+
{
|
332
|
+
int32_t sub_bucket_count_magnitude;
|
333
|
+
int64_t largest_value_with_single_unit_resolution;
|
334
|
+
|
335
|
+
if (lowest_discernible_value < 1 ||
|
336
|
+
significant_figures < 1 || 5 < significant_figures ||
|
337
|
+
lowest_discernible_value * 2 > highest_trackable_value)
|
338
|
+
{
|
339
|
+
return EINVAL;
|
340
|
+
}
|
341
|
+
|
342
|
+
cfg->lowest_discernible_value = lowest_discernible_value;
|
343
|
+
cfg->significant_figures = significant_figures;
|
344
|
+
cfg->highest_trackable_value = highest_trackable_value;
|
345
|
+
|
346
|
+
largest_value_with_single_unit_resolution = 2 * power(10, significant_figures);
|
347
|
+
sub_bucket_count_magnitude = (int32_t) ceil(log((double)largest_value_with_single_unit_resolution) / log(2));
|
348
|
+
cfg->sub_bucket_half_count_magnitude = ((sub_bucket_count_magnitude > 1) ? sub_bucket_count_magnitude : 1) - 1;
|
349
|
+
|
350
|
+
double unit_magnitude = log((double)lowest_discernible_value) / log(2);
|
351
|
+
if (INT32_MAX < unit_magnitude)
|
352
|
+
{
|
353
|
+
return EINVAL;
|
354
|
+
}
|
355
|
+
|
356
|
+
cfg->unit_magnitude = (int32_t) unit_magnitude;
|
357
|
+
cfg->sub_bucket_count = (int32_t) pow(2, (cfg->sub_bucket_half_count_magnitude + 1));
|
358
|
+
cfg->sub_bucket_half_count = cfg->sub_bucket_count / 2;
|
359
|
+
cfg->sub_bucket_mask = ((int64_t) cfg->sub_bucket_count - 1) << cfg->unit_magnitude;
|
360
|
+
|
361
|
+
if (cfg->unit_magnitude + cfg->sub_bucket_half_count_magnitude > 61)
|
362
|
+
{
|
363
|
+
return EINVAL;
|
364
|
+
}
|
365
|
+
|
366
|
+
cfg->bucket_count = buckets_needed_to_cover_value(highest_trackable_value, cfg->sub_bucket_count, (int32_t)cfg->unit_magnitude);
|
367
|
+
cfg->counts_len = (cfg->bucket_count + 1) * (cfg->sub_bucket_count / 2);
|
368
|
+
|
369
|
+
return 0;
|
370
|
+
}
|
371
|
+
|
372
|
+
void hdr_init_preallocated(struct hdr_histogram* h, struct hdr_histogram_bucket_config* cfg)
|
373
|
+
{
|
374
|
+
h->lowest_discernible_value = cfg->lowest_discernible_value;
|
375
|
+
h->highest_trackable_value = cfg->highest_trackable_value;
|
376
|
+
h->unit_magnitude = (int32_t)cfg->unit_magnitude;
|
377
|
+
h->significant_figures = (int32_t)cfg->significant_figures;
|
378
|
+
h->sub_bucket_half_count_magnitude = cfg->sub_bucket_half_count_magnitude;
|
379
|
+
h->sub_bucket_half_count = cfg->sub_bucket_half_count;
|
380
|
+
h->sub_bucket_mask = cfg->sub_bucket_mask;
|
381
|
+
h->sub_bucket_count = cfg->sub_bucket_count;
|
382
|
+
h->min_value = INT64_MAX;
|
383
|
+
h->max_value = 0;
|
384
|
+
h->normalizing_index_offset = 0;
|
385
|
+
h->conversion_ratio = 1.0;
|
386
|
+
h->bucket_count = cfg->bucket_count;
|
387
|
+
h->counts_len = cfg->counts_len;
|
388
|
+
h->total_count = 0;
|
389
|
+
}
|
390
|
+
|
391
|
+
int hdr_init(
|
392
|
+
int64_t lowest_discernible_value,
|
393
|
+
int64_t highest_trackable_value,
|
394
|
+
int significant_figures,
|
395
|
+
struct hdr_histogram** result)
|
396
|
+
{
|
397
|
+
int64_t* counts;
|
398
|
+
struct hdr_histogram_bucket_config cfg;
|
399
|
+
struct hdr_histogram* histogram;
|
400
|
+
|
401
|
+
int r = hdr_calculate_bucket_config(lowest_discernible_value, highest_trackable_value, significant_figures, &cfg);
|
402
|
+
if (r)
|
403
|
+
{
|
404
|
+
return r;
|
405
|
+
}
|
406
|
+
|
407
|
+
counts = (int64_t*) hdr_calloc((size_t) cfg.counts_len, sizeof(int64_t));
|
408
|
+
if (!counts)
|
409
|
+
{
|
410
|
+
return ENOMEM;
|
411
|
+
}
|
412
|
+
|
413
|
+
histogram = (struct hdr_histogram*) hdr_calloc(1, sizeof(struct hdr_histogram));
|
414
|
+
if (!histogram)
|
415
|
+
{
|
416
|
+
hdr_free(counts);
|
417
|
+
return ENOMEM;
|
418
|
+
}
|
419
|
+
|
420
|
+
histogram->counts = counts;
|
421
|
+
|
422
|
+
hdr_init_preallocated(histogram, &cfg);
|
423
|
+
*result = histogram;
|
424
|
+
|
425
|
+
return 0;
|
426
|
+
}
|
427
|
+
|
428
|
+
void hdr_close(struct hdr_histogram* h)
|
429
|
+
{
|
430
|
+
if (h) {
|
431
|
+
hdr_free(h->counts);
|
432
|
+
hdr_free(h);
|
433
|
+
}
|
434
|
+
}
|
435
|
+
|
436
|
+
int hdr_alloc(int64_t highest_trackable_value, int significant_figures, struct hdr_histogram** result)
|
437
|
+
{
|
438
|
+
return hdr_init(1, highest_trackable_value, significant_figures, result);
|
439
|
+
}
|
440
|
+
|
441
|
+
/* reset a histogram to zero. */
|
442
|
+
void hdr_reset(struct hdr_histogram *h)
|
443
|
+
{
|
444
|
+
h->total_count=0;
|
445
|
+
h->min_value = INT64_MAX;
|
446
|
+
h->max_value = 0;
|
447
|
+
memset(h->counts, 0, (sizeof(int64_t) * h->counts_len));
|
448
|
+
}
|
449
|
+
|
450
|
+
size_t hdr_get_memory_size(struct hdr_histogram *h)
|
451
|
+
{
|
452
|
+
return sizeof(struct hdr_histogram) + h->counts_len * sizeof(int64_t);
|
453
|
+
}
|
454
|
+
|
455
|
+
/* ## ## ######## ######## ### ######## ######## ###### */
|
456
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## */
|
457
|
+
/* ## ## ## ## ## ## ## ## ## ## ## */
|
458
|
+
/* ## ## ######## ## ## ## ## ## ###### ###### */
|
459
|
+
/* ## ## ## ## ## ######### ## ## ## */
|
460
|
+
/* ## ## ## ## ## ## ## ## ## ## ## */
|
461
|
+
/* ####### ## ######## ## ## ## ######## ###### */
|
462
|
+
|
463
|
+
|
464
|
+
bool hdr_record_value(struct hdr_histogram* h, int64_t value)
|
465
|
+
{
|
466
|
+
return hdr_record_values(h, value, 1);
|
467
|
+
}
|
468
|
+
|
469
|
+
bool hdr_record_value_atomic(struct hdr_histogram* h, int64_t value)
|
470
|
+
{
|
471
|
+
return hdr_record_values_atomic(h, value, 1);
|
472
|
+
}
|
473
|
+
|
474
|
+
bool hdr_record_values(struct hdr_histogram* h, int64_t value, int64_t count)
|
475
|
+
{
|
476
|
+
int32_t counts_index;
|
477
|
+
|
478
|
+
if (value < 0)
|
479
|
+
{
|
480
|
+
return false;
|
481
|
+
}
|
482
|
+
|
483
|
+
counts_index = counts_index_for(h, value);
|
484
|
+
|
485
|
+
if (counts_index < 0 || h->counts_len <= counts_index)
|
486
|
+
{
|
487
|
+
return false;
|
488
|
+
}
|
489
|
+
|
490
|
+
counts_inc_normalised(h, counts_index, count);
|
491
|
+
update_min_max(h, value);
|
492
|
+
|
493
|
+
return true;
|
494
|
+
}
|
495
|
+
|
496
|
+
bool hdr_record_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count)
|
497
|
+
{
|
498
|
+
int32_t counts_index;
|
499
|
+
|
500
|
+
if (value < 0)
|
501
|
+
{
|
502
|
+
return false;
|
503
|
+
}
|
504
|
+
|
505
|
+
counts_index = counts_index_for(h, value);
|
506
|
+
|
507
|
+
if (counts_index < 0 || h->counts_len <= counts_index)
|
508
|
+
{
|
509
|
+
return false;
|
510
|
+
}
|
511
|
+
|
512
|
+
counts_inc_normalised_atomic(h, counts_index, count);
|
513
|
+
update_min_max_atomic(h, value);
|
514
|
+
|
515
|
+
return true;
|
516
|
+
}
|
517
|
+
|
518
|
+
bool hdr_record_corrected_value(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
|
519
|
+
{
|
520
|
+
return hdr_record_corrected_values(h, value, 1, expected_interval);
|
521
|
+
}
|
522
|
+
|
523
|
+
bool hdr_record_corrected_value_atomic(struct hdr_histogram* h, int64_t value, int64_t expected_interval)
|
524
|
+
{
|
525
|
+
return hdr_record_corrected_values_atomic(h, value, 1, expected_interval);
|
526
|
+
}
|
527
|
+
|
528
|
+
bool hdr_record_corrected_values(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
|
529
|
+
{
|
530
|
+
int64_t missing_value;
|
531
|
+
|
532
|
+
if (!hdr_record_values(h, value, count))
|
533
|
+
{
|
534
|
+
return false;
|
535
|
+
}
|
536
|
+
|
537
|
+
if (expected_interval <= 0 || value <= expected_interval)
|
538
|
+
{
|
539
|
+
return true;
|
540
|
+
}
|
541
|
+
|
542
|
+
missing_value = value - expected_interval;
|
543
|
+
for (; missing_value >= expected_interval; missing_value -= expected_interval)
|
544
|
+
{
|
545
|
+
if (!hdr_record_values(h, missing_value, count))
|
546
|
+
{
|
547
|
+
return false;
|
548
|
+
}
|
549
|
+
}
|
550
|
+
|
551
|
+
return true;
|
552
|
+
}
|
553
|
+
|
554
|
+
bool hdr_record_corrected_values_atomic(struct hdr_histogram* h, int64_t value, int64_t count, int64_t expected_interval)
|
555
|
+
{
|
556
|
+
int64_t missing_value;
|
557
|
+
|
558
|
+
if (!hdr_record_values_atomic(h, value, count))
|
559
|
+
{
|
560
|
+
return false;
|
561
|
+
}
|
562
|
+
|
563
|
+
if (expected_interval <= 0 || value <= expected_interval)
|
564
|
+
{
|
565
|
+
return true;
|
566
|
+
}
|
567
|
+
|
568
|
+
missing_value = value - expected_interval;
|
569
|
+
for (; missing_value >= expected_interval; missing_value -= expected_interval)
|
570
|
+
{
|
571
|
+
if (!hdr_record_values_atomic(h, missing_value, count))
|
572
|
+
{
|
573
|
+
return false;
|
574
|
+
}
|
575
|
+
}
|
576
|
+
|
577
|
+
return true;
|
578
|
+
}
|
579
|
+
|
580
|
+
int64_t hdr_add(struct hdr_histogram* h, const struct hdr_histogram* from)
|
581
|
+
{
|
582
|
+
struct hdr_iter iter;
|
583
|
+
int64_t dropped = 0;
|
584
|
+
hdr_iter_recorded_init(&iter, from);
|
585
|
+
|
586
|
+
while (hdr_iter_next(&iter))
|
587
|
+
{
|
588
|
+
int64_t value = iter.value;
|
589
|
+
int64_t count = iter.count;
|
590
|
+
|
591
|
+
if (!hdr_record_values(h, value, count))
|
592
|
+
{
|
593
|
+
dropped += count;
|
594
|
+
}
|
595
|
+
}
|
596
|
+
|
597
|
+
return dropped;
|
598
|
+
}
|
599
|
+
|
600
|
+
int64_t hdr_add_while_correcting_for_coordinated_omission(
|
601
|
+
struct hdr_histogram* h, struct hdr_histogram* from, int64_t expected_interval)
|
602
|
+
{
|
603
|
+
struct hdr_iter iter;
|
604
|
+
int64_t dropped = 0;
|
605
|
+
hdr_iter_recorded_init(&iter, from);
|
606
|
+
|
607
|
+
while (hdr_iter_next(&iter))
|
608
|
+
{
|
609
|
+
int64_t value = iter.value;
|
610
|
+
int64_t count = iter.count;
|
611
|
+
|
612
|
+
if (!hdr_record_corrected_values(h, value, count, expected_interval))
|
613
|
+
{
|
614
|
+
dropped += count;
|
615
|
+
}
|
616
|
+
}
|
617
|
+
|
618
|
+
return dropped;
|
619
|
+
}
|
620
|
+
|
621
|
+
|
622
|
+
|
623
|
+
/* ## ## ### ## ## ## ######## ###### */
|
624
|
+
/* ## ## ## ## ## ## ## ## ## ## */
|
625
|
+
/* ## ## ## ## ## ## ## ## ## */
|
626
|
+
/* ## ## ## ## ## ## ## ###### ###### */
|
627
|
+
/* ## ## ######### ## ## ## ## ## */
|
628
|
+
/* ## ## ## ## ## ## ## ## ## ## */
|
629
|
+
/* ### ## ## ######## ####### ######## ###### */
|
630
|
+
|
631
|
+
|
632
|
+
int64_t hdr_max(const struct hdr_histogram* h)
|
633
|
+
{
|
634
|
+
if (0 == h->max_value)
|
635
|
+
{
|
636
|
+
return 0;
|
637
|
+
}
|
638
|
+
|
639
|
+
return highest_equivalent_value(h, h->max_value);
|
640
|
+
}
|
641
|
+
|
642
|
+
int64_t hdr_min(const struct hdr_histogram* h)
|
643
|
+
{
|
644
|
+
if (0 < hdr_count_at_index(h, 0))
|
645
|
+
{
|
646
|
+
return 0;
|
647
|
+
}
|
648
|
+
|
649
|
+
return non_zero_min(h);
|
650
|
+
}
|
651
|
+
|
652
|
+
int64_t hdr_value_at_percentile(const struct hdr_histogram* h, double percentile)
|
653
|
+
{
|
654
|
+
struct hdr_iter iter;
|
655
|
+
int64_t total = 0;
|
656
|
+
double requested_percentile = percentile < 100.0 ? percentile : 100.0;
|
657
|
+
int64_t count_at_percentile =
|
658
|
+
(int64_t) (((requested_percentile / 100) * h->total_count) + 0.5);
|
659
|
+
count_at_percentile = count_at_percentile > 1 ? count_at_percentile : 1;
|
660
|
+
|
661
|
+
hdr_iter_init(&iter, h);
|
662
|
+
|
663
|
+
while (hdr_iter_next(&iter))
|
664
|
+
{
|
665
|
+
total += iter.count;
|
666
|
+
|
667
|
+
if (total >= count_at_percentile)
|
668
|
+
{
|
669
|
+
int64_t value_from_index = iter.value;
|
670
|
+
return highest_equivalent_value(h, value_from_index);
|
671
|
+
}
|
672
|
+
}
|
673
|
+
|
674
|
+
return 0;
|
675
|
+
}
|
676
|
+
|
677
|
+
int hdr_value_at_percentiles(const struct hdr_histogram *h, const double *percentiles, int64_t *values, size_t length)
|
678
|
+
{
|
679
|
+
if (NULL == percentiles || NULL == values)
|
680
|
+
{
|
681
|
+
return EINVAL;
|
682
|
+
}
|
683
|
+
|
684
|
+
struct hdr_iter iter;
|
685
|
+
const int64_t total_count = h->total_count;
|
686
|
+
// to avoid allocations we use the values array for intermediate computation
|
687
|
+
// i.e. to store the expected cumulative count at each percentile
|
688
|
+
for (size_t i = 0; i < length; i++)
|
689
|
+
{
|
690
|
+
const double requested_percentile = percentiles[i] < 100.0 ? percentiles[i] : 100.0;
|
691
|
+
const int64_t count_at_percentile =
|
692
|
+
(int64_t) (((requested_percentile / 100) * total_count) + 0.5);
|
693
|
+
values[i] = count_at_percentile > 1 ? count_at_percentile : 1;
|
694
|
+
}
|
695
|
+
|
696
|
+
hdr_iter_init(&iter, h);
|
697
|
+
int64_t total = 0;
|
698
|
+
size_t at_pos = 0;
|
699
|
+
while (hdr_iter_next(&iter) && at_pos < length)
|
700
|
+
{
|
701
|
+
total += iter.count;
|
702
|
+
while (total >= values[at_pos] && at_pos < length)
|
703
|
+
{
|
704
|
+
values[at_pos] = highest_equivalent_value(h, iter.value);
|
705
|
+
at_pos++;
|
706
|
+
}
|
707
|
+
}
|
708
|
+
return 0;
|
709
|
+
}
|
710
|
+
|
711
|
+
double hdr_mean(const struct hdr_histogram* h)
|
712
|
+
{
|
713
|
+
struct hdr_iter iter;
|
714
|
+
int64_t total = 0;
|
715
|
+
|
716
|
+
hdr_iter_init(&iter, h);
|
717
|
+
|
718
|
+
while (hdr_iter_next(&iter))
|
719
|
+
{
|
720
|
+
if (0 != iter.count)
|
721
|
+
{
|
722
|
+
total += iter.count * hdr_median_equivalent_value(h, iter.value);
|
723
|
+
}
|
724
|
+
}
|
725
|
+
|
726
|
+
return (total * 1.0) / h->total_count;
|
727
|
+
}
|
728
|
+
|
729
|
+
double hdr_stddev(const struct hdr_histogram* h)
|
730
|
+
{
|
731
|
+
double mean = hdr_mean(h);
|
732
|
+
double geometric_dev_total = 0.0;
|
733
|
+
|
734
|
+
struct hdr_iter iter;
|
735
|
+
hdr_iter_init(&iter, h);
|
736
|
+
|
737
|
+
while (hdr_iter_next(&iter))
|
738
|
+
{
|
739
|
+
if (0 != iter.count)
|
740
|
+
{
|
741
|
+
double dev = (hdr_median_equivalent_value(h, iter.value) * 1.0) - mean;
|
742
|
+
geometric_dev_total += (dev * dev) * iter.count;
|
743
|
+
}
|
744
|
+
}
|
745
|
+
|
746
|
+
return sqrt(geometric_dev_total / h->total_count);
|
747
|
+
}
|
748
|
+
|
749
|
+
bool hdr_values_are_equivalent(const struct hdr_histogram* h, int64_t a, int64_t b)
|
750
|
+
{
|
751
|
+
return lowest_equivalent_value(h, a) == lowest_equivalent_value(h, b);
|
752
|
+
}
|
753
|
+
|
754
|
+
int64_t hdr_lowest_equivalent_value(const struct hdr_histogram* h, int64_t value)
|
755
|
+
{
|
756
|
+
return lowest_equivalent_value(h, value);
|
757
|
+
}
|
758
|
+
|
759
|
+
int64_t hdr_count_at_value(const struct hdr_histogram* h, int64_t value)
|
760
|
+
{
|
761
|
+
return counts_get_normalised(h, counts_index_for(h, value));
|
762
|
+
}
|
763
|
+
|
764
|
+
int64_t hdr_count_at_index(const struct hdr_histogram* h, int32_t index)
|
765
|
+
{
|
766
|
+
return counts_get_normalised(h, index);
|
767
|
+
}
|
768
|
+
|
769
|
+
|
770
|
+
/* #### ######## ######## ######## ### ######## ####### ######## ###### */
|
771
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
772
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
773
|
+
/* ## ## ###### ######## ## ## ## ## ## ######## ###### */
|
774
|
+
/* ## ## ## ## ## ######### ## ## ## ## ## ## */
|
775
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
776
|
+
/* #### ## ######## ## ## ## ## ## ####### ## ## ###### */
|
777
|
+
|
778
|
+
|
779
|
+
static bool has_buckets(struct hdr_iter* iter)
|
780
|
+
{
|
781
|
+
return iter->counts_index < iter->h->counts_len;
|
782
|
+
}
|
783
|
+
|
784
|
+
static bool has_next(struct hdr_iter* iter)
|
785
|
+
{
|
786
|
+
return iter->cumulative_count < iter->total_count;
|
787
|
+
}
|
788
|
+
|
789
|
+
static bool move_next(struct hdr_iter* iter)
|
790
|
+
{
|
791
|
+
iter->counts_index++;
|
792
|
+
|
793
|
+
if (!has_buckets(iter))
|
794
|
+
{
|
795
|
+
return false;
|
796
|
+
}
|
797
|
+
|
798
|
+
iter->count = counts_get_normalised(iter->h, iter->counts_index);
|
799
|
+
iter->cumulative_count += iter->count;
|
800
|
+
|
801
|
+
iter->value = hdr_value_at_index(iter->h, iter->counts_index);
|
802
|
+
iter->highest_equivalent_value = highest_equivalent_value(iter->h, iter->value);
|
803
|
+
iter->lowest_equivalent_value = lowest_equivalent_value(iter->h, iter->value);
|
804
|
+
iter->median_equivalent_value = hdr_median_equivalent_value(iter->h, iter->value);
|
805
|
+
|
806
|
+
return true;
|
807
|
+
}
|
808
|
+
|
809
|
+
static int64_t peek_next_value_from_index(struct hdr_iter* iter)
|
810
|
+
{
|
811
|
+
return hdr_value_at_index(iter->h, iter->counts_index + 1);
|
812
|
+
}
|
813
|
+
|
814
|
+
static bool next_value_greater_than_reporting_level_upper_bound(
|
815
|
+
struct hdr_iter *iter, int64_t reporting_level_upper_bound)
|
816
|
+
{
|
817
|
+
if (iter->counts_index >= iter->h->counts_len)
|
818
|
+
{
|
819
|
+
return false;
|
820
|
+
}
|
821
|
+
|
822
|
+
return peek_next_value_from_index(iter) > reporting_level_upper_bound;
|
823
|
+
}
|
824
|
+
|
825
|
+
static bool basic_iter_next(struct hdr_iter *iter)
|
826
|
+
{
|
827
|
+
if (!has_next(iter) || iter->counts_index >= iter->h->counts_len)
|
828
|
+
{
|
829
|
+
return false;
|
830
|
+
}
|
831
|
+
|
832
|
+
move_next(iter);
|
833
|
+
|
834
|
+
return true;
|
835
|
+
}
|
836
|
+
|
837
|
+
static void update_iterated_values(struct hdr_iter* iter, int64_t new_value_iterated_to)
|
838
|
+
{
|
839
|
+
iter->value_iterated_from = iter->value_iterated_to;
|
840
|
+
iter->value_iterated_to = new_value_iterated_to;
|
841
|
+
}
|
842
|
+
|
843
|
+
static bool all_values_iter_next(struct hdr_iter* iter)
|
844
|
+
{
|
845
|
+
bool result = move_next(iter);
|
846
|
+
|
847
|
+
if (result)
|
848
|
+
{
|
849
|
+
update_iterated_values(iter, iter->value);
|
850
|
+
}
|
851
|
+
|
852
|
+
return result;
|
853
|
+
}
|
854
|
+
|
855
|
+
void hdr_iter_init(struct hdr_iter* iter, const struct hdr_histogram* h)
|
856
|
+
{
|
857
|
+
iter->h = h;
|
858
|
+
|
859
|
+
iter->counts_index = -1;
|
860
|
+
iter->total_count = h->total_count;
|
861
|
+
iter->count = 0;
|
862
|
+
iter->cumulative_count = 0;
|
863
|
+
iter->value = 0;
|
864
|
+
iter->highest_equivalent_value = 0;
|
865
|
+
iter->value_iterated_from = 0;
|
866
|
+
iter->value_iterated_to = 0;
|
867
|
+
|
868
|
+
iter->_next_fp = all_values_iter_next;
|
869
|
+
}
|
870
|
+
|
871
|
+
bool hdr_iter_next(struct hdr_iter* iter)
|
872
|
+
{
|
873
|
+
return iter->_next_fp(iter);
|
874
|
+
}
|
875
|
+
|
876
|
+
/* ######## ######## ######## ###### ######## ## ## ######## #### ## ######## ###### */
|
877
|
+
/* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## ## */
|
878
|
+
/* ## ## ## ## ## ## ## #### ## ## ## ## ## ## */
|
879
|
+
/* ######## ###### ######## ## ###### ## ## ## ## ## ## ###### ###### */
|
880
|
+
/* ## ## ## ## ## ## ## #### ## ## ## ## ## */
|
881
|
+
/* ## ## ## ## ## ## ## ## ### ## ## ## ## ## ## */
|
882
|
+
/* ## ######## ## ## ###### ######## ## ## ## #### ######## ######## ###### */
|
883
|
+
|
884
|
+
static bool percentile_iter_next(struct hdr_iter* iter)
|
885
|
+
{
|
886
|
+
int64_t temp, half_distance, percentile_reporting_ticks;
|
887
|
+
|
888
|
+
struct hdr_iter_percentiles* percentiles = &iter->specifics.percentiles;
|
889
|
+
|
890
|
+
if (!has_next(iter))
|
891
|
+
{
|
892
|
+
if (percentiles->seen_last_value)
|
893
|
+
{
|
894
|
+
return false;
|
895
|
+
}
|
896
|
+
|
897
|
+
percentiles->seen_last_value = true;
|
898
|
+
percentiles->percentile = 100.0;
|
899
|
+
|
900
|
+
return true;
|
901
|
+
}
|
902
|
+
|
903
|
+
if (iter->counts_index == -1 && !basic_iter_next(iter))
|
904
|
+
{
|
905
|
+
return false;
|
906
|
+
}
|
907
|
+
|
908
|
+
do
|
909
|
+
{
|
910
|
+
double current_percentile = (100.0 * (double) iter->cumulative_count) / iter->h->total_count;
|
911
|
+
if (iter->count != 0 &&
|
912
|
+
percentiles->percentile_to_iterate_to <= current_percentile)
|
913
|
+
{
|
914
|
+
update_iterated_values(iter, highest_equivalent_value(iter->h, iter->value));
|
915
|
+
|
916
|
+
percentiles->percentile = percentiles->percentile_to_iterate_to;
|
917
|
+
temp = (int64_t)(log(100 / (100.0 - (percentiles->percentile_to_iterate_to))) / log(2)) + 1;
|
918
|
+
half_distance = (int64_t) pow(2, (double) temp);
|
919
|
+
percentile_reporting_ticks = percentiles->ticks_per_half_distance * half_distance;
|
920
|
+
percentiles->percentile_to_iterate_to += 100.0 / percentile_reporting_ticks;
|
921
|
+
|
922
|
+
return true;
|
923
|
+
}
|
924
|
+
}
|
925
|
+
while (basic_iter_next(iter));
|
926
|
+
|
927
|
+
return true;
|
928
|
+
}
|
929
|
+
|
930
|
+
void hdr_iter_percentile_init(struct hdr_iter* iter, const struct hdr_histogram* h, int32_t ticks_per_half_distance)
|
931
|
+
{
|
932
|
+
iter->h = h;
|
933
|
+
|
934
|
+
hdr_iter_init(iter, h);
|
935
|
+
|
936
|
+
iter->specifics.percentiles.seen_last_value = false;
|
937
|
+
iter->specifics.percentiles.ticks_per_half_distance = ticks_per_half_distance;
|
938
|
+
iter->specifics.percentiles.percentile_to_iterate_to = 0.0;
|
939
|
+
iter->specifics.percentiles.percentile = 0.0;
|
940
|
+
|
941
|
+
iter->_next_fp = percentile_iter_next;
|
942
|
+
}
|
943
|
+
|
944
|
+
static void format_line_string(char* str, size_t len, int significant_figures, format_type format)
|
945
|
+
{
|
946
|
+
#if defined(_MSC_VER)
|
947
|
+
#define snprintf _snprintf
|
948
|
+
#pragma warning(push)
|
949
|
+
#pragma warning(disable: 4996)
|
950
|
+
#endif
|
951
|
+
const char* format_str = "%s%d%s";
|
952
|
+
|
953
|
+
switch (format)
|
954
|
+
{
|
955
|
+
case CSV:
|
956
|
+
snprintf(str, len, format_str, "%.", significant_figures, "f,%f,%d,%.2f\n");
|
957
|
+
break;
|
958
|
+
case CLASSIC:
|
959
|
+
snprintf(str, len, format_str, "%12.", significant_figures, "f %12f %12d %12.2f\n");
|
960
|
+
break;
|
961
|
+
default:
|
962
|
+
snprintf(str, len, format_str, "%12.", significant_figures, "f %12f %12d %12.2f\n");
|
963
|
+
}
|
964
|
+
#if defined(_MSC_VER)
|
965
|
+
#undef snprintf
|
966
|
+
#pragma warning(pop)
|
967
|
+
#endif
|
968
|
+
}
|
969
|
+
|
970
|
+
|
971
|
+
/* ######## ######## ###### ####### ######## ######## ######## ######## */
|
972
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
973
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
974
|
+
/* ######## ###### ## ## ## ######## ## ## ###### ## ## */
|
975
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
976
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
977
|
+
/* ## ## ######## ###### ####### ## ## ######## ######## ######## */
|
978
|
+
|
979
|
+
|
980
|
+
static bool recorded_iter_next(struct hdr_iter* iter)
|
981
|
+
{
|
982
|
+
while (basic_iter_next(iter))
|
983
|
+
{
|
984
|
+
if (iter->count != 0)
|
985
|
+
{
|
986
|
+
update_iterated_values(iter, iter->value);
|
987
|
+
|
988
|
+
iter->specifics.recorded.count_added_in_this_iteration_step = iter->count;
|
989
|
+
return true;
|
990
|
+
}
|
991
|
+
}
|
992
|
+
|
993
|
+
return false;
|
994
|
+
}
|
995
|
+
|
996
|
+
void hdr_iter_recorded_init(struct hdr_iter* iter, const struct hdr_histogram* h)
|
997
|
+
{
|
998
|
+
hdr_iter_init(iter, h);
|
999
|
+
|
1000
|
+
iter->specifics.recorded.count_added_in_this_iteration_step = 0;
|
1001
|
+
|
1002
|
+
iter->_next_fp = recorded_iter_next;
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
/* ## #### ## ## ######## ### ######## */
|
1006
|
+
/* ## ## ### ## ## ## ## ## ## */
|
1007
|
+
/* ## ## #### ## ## ## ## ## ## */
|
1008
|
+
/* ## ## ## ## ## ###### ## ## ######## */
|
1009
|
+
/* ## ## ## #### ## ######### ## ## */
|
1010
|
+
/* ## ## ## ### ## ## ## ## ## */
|
1011
|
+
/* ######## #### ## ## ######## ## ## ## ## */
|
1012
|
+
|
1013
|
+
|
1014
|
+
static bool iter_linear_next(struct hdr_iter* iter)
|
1015
|
+
{
|
1016
|
+
struct hdr_iter_linear* linear = &iter->specifics.linear;
|
1017
|
+
|
1018
|
+
linear->count_added_in_this_iteration_step = 0;
|
1019
|
+
|
1020
|
+
if (has_next(iter) ||
|
1021
|
+
next_value_greater_than_reporting_level_upper_bound(
|
1022
|
+
iter, linear->next_value_reporting_level_lowest_equivalent))
|
1023
|
+
{
|
1024
|
+
do
|
1025
|
+
{
|
1026
|
+
if (iter->value >= linear->next_value_reporting_level_lowest_equivalent)
|
1027
|
+
{
|
1028
|
+
update_iterated_values(iter, linear->next_value_reporting_level);
|
1029
|
+
|
1030
|
+
linear->next_value_reporting_level += linear->value_units_per_bucket;
|
1031
|
+
linear->next_value_reporting_level_lowest_equivalent =
|
1032
|
+
lowest_equivalent_value(iter->h, linear->next_value_reporting_level);
|
1033
|
+
|
1034
|
+
return true;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
if (!move_next(iter))
|
1038
|
+
{
|
1039
|
+
return true;
|
1040
|
+
}
|
1041
|
+
|
1042
|
+
linear->count_added_in_this_iteration_step += iter->count;
|
1043
|
+
}
|
1044
|
+
while (true);
|
1045
|
+
}
|
1046
|
+
|
1047
|
+
return false;
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
|
1051
|
+
void hdr_iter_linear_init(struct hdr_iter* iter, const struct hdr_histogram* h, int64_t value_units_per_bucket)
|
1052
|
+
{
|
1053
|
+
hdr_iter_init(iter, h);
|
1054
|
+
|
1055
|
+
iter->specifics.linear.count_added_in_this_iteration_step = 0;
|
1056
|
+
iter->specifics.linear.value_units_per_bucket = value_units_per_bucket;
|
1057
|
+
iter->specifics.linear.next_value_reporting_level = value_units_per_bucket;
|
1058
|
+
iter->specifics.linear.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_per_bucket);
|
1059
|
+
|
1060
|
+
iter->_next_fp = iter_linear_next;
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
/* ## ####### ###### ### ######## #### ######## ## ## ## ## #### ###### */
|
1064
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## ### ### ## ## ## */
|
1065
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## #### #### ## ## */
|
1066
|
+
/* ## ## ## ## #### ## ## ######## ## ## ######### ## ### ## ## ## */
|
1067
|
+
/* ## ## ## ## ## ######### ## ## ## ## ## ## ## ## ## ## */
|
1068
|
+
/* ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## */
|
1069
|
+
/* ######## ####### ###### ## ## ## ## #### ## ## ## ## ## #### ###### */
|
1070
|
+
|
1071
|
+
static bool log_iter_next(struct hdr_iter *iter)
|
1072
|
+
{
|
1073
|
+
struct hdr_iter_log* logarithmic = &iter->specifics.log;
|
1074
|
+
|
1075
|
+
logarithmic->count_added_in_this_iteration_step = 0;
|
1076
|
+
|
1077
|
+
if (has_next(iter) ||
|
1078
|
+
next_value_greater_than_reporting_level_upper_bound(
|
1079
|
+
iter, logarithmic->next_value_reporting_level_lowest_equivalent))
|
1080
|
+
{
|
1081
|
+
do
|
1082
|
+
{
|
1083
|
+
if (iter->value >= logarithmic->next_value_reporting_level_lowest_equivalent)
|
1084
|
+
{
|
1085
|
+
update_iterated_values(iter, logarithmic->next_value_reporting_level);
|
1086
|
+
|
1087
|
+
logarithmic->next_value_reporting_level *= (int64_t)logarithmic->log_base;
|
1088
|
+
logarithmic->next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(iter->h, logarithmic->next_value_reporting_level);
|
1089
|
+
|
1090
|
+
return true;
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
if (!move_next(iter))
|
1094
|
+
{
|
1095
|
+
return true;
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
logarithmic->count_added_in_this_iteration_step += iter->count;
|
1099
|
+
}
|
1100
|
+
while (true);
|
1101
|
+
}
|
1102
|
+
|
1103
|
+
return false;
|
1104
|
+
}
|
1105
|
+
|
1106
|
+
void hdr_iter_log_init(
|
1107
|
+
struct hdr_iter* iter,
|
1108
|
+
const struct hdr_histogram* h,
|
1109
|
+
int64_t value_units_first_bucket,
|
1110
|
+
double log_base)
|
1111
|
+
{
|
1112
|
+
hdr_iter_init(iter, h);
|
1113
|
+
iter->specifics.log.count_added_in_this_iteration_step = 0;
|
1114
|
+
iter->specifics.log.log_base = log_base;
|
1115
|
+
iter->specifics.log.next_value_reporting_level = value_units_first_bucket;
|
1116
|
+
iter->specifics.log.next_value_reporting_level_lowest_equivalent = lowest_equivalent_value(h, value_units_first_bucket);
|
1117
|
+
|
1118
|
+
iter->_next_fp = log_iter_next;
|
1119
|
+
}
|
1120
|
+
|
1121
|
+
/* Printing. */
|
1122
|
+
|
1123
|
+
static const char* format_head_string(format_type format)
|
1124
|
+
{
|
1125
|
+
switch (format)
|
1126
|
+
{
|
1127
|
+
case CSV:
|
1128
|
+
return "%s,%s,%s,%s\n";
|
1129
|
+
case CLASSIC:
|
1130
|
+
default:
|
1131
|
+
return "%12s %12s %12s %12s\n\n";
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
static const char CLASSIC_FOOTER[] =
|
1136
|
+
"#[Mean = %12.3f, StdDeviation = %12.3f]\n"
|
1137
|
+
"#[Max = %12.3f, Total count = %12" PRIu64 "]\n"
|
1138
|
+
"#[Buckets = %12d, SubBuckets = %12d]\n";
|
1139
|
+
|
1140
|
+
int hdr_percentiles_print(
|
1141
|
+
struct hdr_histogram* h, FILE* stream, int32_t ticks_per_half_distance,
|
1142
|
+
double value_scale, format_type format)
|
1143
|
+
{
|
1144
|
+
char line_format[25];
|
1145
|
+
const char* head_format;
|
1146
|
+
int rc = 0;
|
1147
|
+
struct hdr_iter iter;
|
1148
|
+
struct hdr_iter_percentiles * percentiles;
|
1149
|
+
|
1150
|
+
format_line_string(line_format, 25, h->significant_figures, format);
|
1151
|
+
head_format = format_head_string(format);
|
1152
|
+
|
1153
|
+
hdr_iter_percentile_init(&iter, h, ticks_per_half_distance);
|
1154
|
+
|
1155
|
+
if (fprintf(
|
1156
|
+
stream, head_format,
|
1157
|
+
"Value", "Percentile", "TotalCount", "1/(1-Percentile)") < 0)
|
1158
|
+
{
|
1159
|
+
rc = EIO;
|
1160
|
+
goto cleanup;
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
percentiles = &iter.specifics.percentiles;
|
1164
|
+
while (hdr_iter_next(&iter))
|
1165
|
+
{
|
1166
|
+
double value = iter.highest_equivalent_value / value_scale;
|
1167
|
+
double percentile = percentiles->percentile / 100.0;
|
1168
|
+
int64_t total_count = iter.cumulative_count;
|
1169
|
+
double inverted_percentile = (1.0 / (1.0 - percentile));
|
1170
|
+
|
1171
|
+
if (fprintf(
|
1172
|
+
stream, line_format, value, percentile, total_count, inverted_percentile) < 0)
|
1173
|
+
{
|
1174
|
+
rc = EIO;
|
1175
|
+
goto cleanup;
|
1176
|
+
}
|
1177
|
+
}
|
1178
|
+
|
1179
|
+
if (CLASSIC == format)
|
1180
|
+
{
|
1181
|
+
double mean = hdr_mean(h) / value_scale;
|
1182
|
+
double stddev = hdr_stddev(h) / value_scale;
|
1183
|
+
double max = hdr_max(h) / value_scale;
|
1184
|
+
|
1185
|
+
if (fprintf(
|
1186
|
+
stream, CLASSIC_FOOTER, mean, stddev, max,
|
1187
|
+
h->total_count, h->bucket_count, h->sub_bucket_count) < 0)
|
1188
|
+
{
|
1189
|
+
rc = EIO;
|
1190
|
+
goto cleanup;
|
1191
|
+
}
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
cleanup:
|
1195
|
+
return rc;
|
1196
|
+
}
|