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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]