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

Reply via email to