This is an automated email from the ASF dual-hosted git repository. kgiusti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/main by this push: new 92419a7 DISPATCH-1487: lessen hash overhead by avoiding byte iterator reads 92419a7 is described below commit 92419a7ad8e7d56d1cf31e077ab948a29ceeb169 Author: Kenneth Giusti <kgiu...@apache.org> AuthorDate: Tue Sep 28 14:23:49 2021 -0400 DISPATCH-1487: lessen hash overhead by avoiding byte iterator reads This closes #1377 --- include/qpid/dispatch/iterator.h | 18 ++++++++++++--- src/iterator.c | 49 +++++++++++++++++++++++++++++----------- tests/field_test.c | 30 ++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 16 deletions(-) diff --git a/include/qpid/dispatch/iterator.h b/include/qpid/dispatch/iterator.h index 9a1a3f8..c580a1c 100644 --- a/include/qpid/dispatch/iterator.h +++ b/include/qpid/dispatch/iterator.h @@ -316,11 +316,23 @@ bool qd_iterator_prefix(qd_iterator_t *iter, const char *prefix); bool qd_iterator_prefix_ptr(const qd_iterator_pointer_t *ptr, uint32_t skip, const char *prefix); /** - * Copy the iterator's view into buffer up to a maximum of n bytes. Cursor is - * advanced by the number of bytes copied. There is no trailing '\0' added. + * Copy the iterator's view into buffer up to a maximum of n bytes. View is + * reset to the beginning and cursor is advanced by the number of bytes + * copied. There is no trailing '\0' added. + * + * @return number of bytes copied. + */ +size_t qd_iterator_ncopy(qd_iterator_t *iter, uint8_t *buffer, size_t n); + +/** + * Copy the iterator's view into buffer up to a maximum of n octets. Unlike + * qd_iterator_ncopy the view is not reset before the copy: copying begins at + * the current cursor position. The cursor is advanced by the number of bytes + * copied. There is no trailing '\0' added. + * * @return number of bytes copied. */ -int qd_iterator_ncopy(qd_iterator_t *iter, unsigned char* buffer, int n); +size_t qd_iterator_ncopy_octets(qd_iterator_t *iter, uint8_t *buffer, size_t n); /** * Return a new copy of the iterator's view, with a trailing '\0' added. The diff --git a/src/iterator.c b/src/iterator.c index 7de9d63..b453164 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -534,6 +534,26 @@ static inline bool iterator_field_equal(qd_iterator_t *iter, const unsigned char } +// fast view-agnostic copy: copy out up to n bytes from the current location in +// the iterator view, advance cursor +// +static inline size_t iterator_view_copy(qd_iterator_t *iter, uint8_t *buffer, size_t n) +{ + int i = 0; + + assert(iter); + + while (i < n && !iterator_at_end(iter)) { + if (!in_field_data(iter)) { + buffer[i++] = qd_iterator_octet(iter); + } else { + i += iterator_field_ncopy(iter, &buffer[i], n - i); + break; + } + } + return i; +} + static void qd_iterator_free_hash_segments(qd_iterator_t *iter) { qd_hash_segment_t *seg = DEQ_HEAD(iter->hash_segments); @@ -945,22 +965,21 @@ int qd_iterator_length(const qd_iterator_t *iter) } -int qd_iterator_ncopy(qd_iterator_t *iter, unsigned char* buffer, int n) +size_t qd_iterator_ncopy(qd_iterator_t *iter, unsigned char* buffer, size_t n) { if (!iter) return 0; qd_iterator_reset(iter); - int i = 0; - while (i < n && !iterator_at_end(iter)) { - if (!in_field_data(iter)) { - buffer[i++] = qd_iterator_octet(iter); - } else { - i += iterator_field_ncopy(iter, &buffer[i], n - i); - break; - } - } - return i; + return iterator_view_copy(iter, (uint8_t *) buffer, n); +} + + +size_t qd_iterator_ncopy_octets(qd_iterator_t *iter, uint8_t *buffer, size_t n) +{ + if (!iter) + return 0; + return iterator_view_copy(iter, (uint8_t *) buffer, n); } @@ -1051,10 +1070,14 @@ static void qd_insert_hash_segment(qd_iterator_t *iter, uint32_t *hash, int segm uint32_t qd_iterator_hash_view(qd_iterator_t *iter) { uint32_t hash = HASH_INIT; + uint8_t buffer[64]; qd_iterator_reset(iter); - while (!iterator_at_end(iter)) - hash = HASH_COMPUTE(hash, qd_iterator_octet(iter)); + while (!iterator_at_end(iter)) { + size_t count = iterator_view_copy(iter, buffer, sizeof(buffer)); + for (int i = 0; i < count; ++i) + hash = HASH_COMPUTE(hash, buffer[i]); + } return hash; } diff --git a/tests/field_test.c b/tests/field_test.c index c88b9b7..a4008c8 100644 --- a/tests/field_test.c +++ b/tests/field_test.c @@ -1113,6 +1113,35 @@ static char *test_prefix_hash_with_space(void *context) } +static char *test_iterator_copy_octet(void *context) +{ + // verify qd_iterator_ncopy_octets() + + char *result = 0; + uint8_t buffer[4]; + const char *expected[] = {"onl", "y/s", "ee/", "thi", "s"}; + + qd_iterator_t *iter = qd_iterator_string("amqp://my.host.com:666/only/see/this", + ITER_VIEW_ADDRESS_NO_HOST); + int i = 0; + while (!qd_iterator_end(iter)) { + memset(buffer, 0, sizeof(buffer)); + size_t count = qd_iterator_ncopy_octets(iter, buffer, 3); + if (count != strlen(expected[i]) || memcmp(buffer, expected[i], count) != 0) { + fprintf(stderr, "qd_iterator_ncopy_octets failed,\n" + "Expected %zu octets set to '%s' got %zu octets set to '%.3s'\n", + strlen(expected[i]), expected[i], + count, (char *)buffer); + result = "qd_iterator_ncopy_octets failed"; + break; + } + ++i; + } + qd_iterator_free(iter); + return result; +} + + int field_tests(void) { int result = 0; @@ -1144,6 +1173,7 @@ int field_tests(void) TEST_CASE(test_qd_hash_retrieve_prefix_separator_exact_match_dot_at_end_1, 0); TEST_CASE(test_prefix_hash, 0); TEST_CASE(test_prefix_hash_with_space, 0); + TEST_CASE(test_iterator_copy_octet, 0); qd_iterator_set_address(true, "my-area", "my-router"); TEST_CASE(test_view_address_hash_edge, 0); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org