From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id C06525A66 for ; Fri, 10 Jul 2015 11:12:20 +0200 (CEST) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP; 10 Jul 2015 02:12:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,446,1432623600"; d="scan'208";a="521914596" Received: from bricha3-mobl3.ger.corp.intel.com ([10.237.208.63]) by FMSMGA003.fm.intel.com with SMTP; 10 Jul 2015 02:12:00 -0700 Received: by (sSMTP sendmail emulation); Fri, 10 Jul 2015 10:11:59 +0025 Date: Fri, 10 Jul 2015 10:11:59 +0100 From: Bruce Richardson To: Pablo de Lara Message-ID: <20150710091159.GA10556@bricha3-MOBL3> References: <1436444378-29106-2-git-send-email-pablo.de.lara.guarch@intel.com> <1436460870-30022-1-git-send-email-pablo.de.lara.guarch@intel.com> <1436460870-30022-2-git-send-email-pablo.de.lara.guarch@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1436460870-30022-2-git-send-email-pablo.de.lara.guarch@intel.com> Organization: Intel Shannon Ltd. User-Agent: Mutt/1.5.23 (2014-03-12) Cc: dev@dpdk.org Subject: Re: [dpdk-dev] [PATCH v4] test/hash: improve hash unit tests X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Jul 2015 09:12:21 -0000 On Thu, Jul 09, 2015 at 05:54:30PM +0100, Pablo de Lara wrote: > Add new unit test for calculating the average table utilization, > using random keys, based on number of entries that can be added > until we encounter one that cannot be added (bucket if full). > > Also, replace current hash_perf unit test to see performance more clear. s/clear/clearly/ > The current hash_perf unit test takes too long and add keys that > may or may not fit in the table and look up/delete that may not be > in the table. This new unit test gets a set of keys that we know > that fits in the table, and then measure the time to add/look up/delete > them. > > Mind that performance numbers include time to take a random key s/Mind/Note/ > from a pre-made array of keys, plus a quick check of return value. > Also, as stated above, expect higher numbers, as all operations > in the new unit tests will be successful, which means that > it will take more time, than mixing both successful and unsuccesful > operations. > > Signed-off-by: Pablo de Lara Looks good, Pablo. Thomas, perhaps you could make the above minor changes to the commit log when applying the patch. Acked-by: Bruce Richardson > --- > app/test/test_hash.c | 66 +++- > app/test/test_hash_perf.c | 923 ++++++++++++++++++++-------------------------- > 2 files changed, 458 insertions(+), 531 deletions(-) > > diff --git a/app/test/test_hash.c b/app/test/test_hash.c > index 4300de9..7c71ed6 100644 > --- a/app/test/test_hash.c > +++ b/app/test/test_hash.c > @@ -190,7 +190,7 @@ test_crc32_hash_alg_equiv(void) > unsigned i, j; > size_t data_len; > > - printf("# CRC32 implementations equivalence test\n"); > + printf("\n# CRC32 implementations equivalence test\n"); > for (i = 0; i < CRC32_ITERATIONS; i++) { > /* Randomizing data_len of data set */ > data_len = (size_t) ((rte_rand() % sizeof(data64)) + 1); > @@ -785,7 +785,7 @@ fbk_hash_unit_test(void) > > /* Try creating hashes with invalid parameters */ > printf("# Testing hash creation with invalid parameters " > - "- expert error msgs\n"); > + "- expect error msgs\n"); > handle = rte_fbk_hash_create(&invalid_params_1); > RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed"); > > @@ -1087,6 +1087,7 @@ static int test_hash_creation_with_bad_parameters(void) > } > > rte_hash_free(handle); > + printf("# Test successful. No more errors expected\n"); > > return 0; > } > @@ -1147,6 +1148,65 @@ test_hash_creation_with_good_parameters(void) > return 0; > } > > +#define ITERATIONS 50 > +/* > + * Test to see the average table utilization (entries added/max entries) > + * before hitting a random entry that cannot be added > + */ > +static int test_average_table_utilization(void) > +{ > + struct rte_hash *handle; > + uint8_t simple_key[RTE_HASH_KEY_LENGTH_MAX]; > + unsigned i, j; > + unsigned added_keys, average_keys_added = 0; > + int ret; > + > + printf("\n# Running test to determine average utilization" > + "\n before adding elements begins to fail\n"); > + printf("Measuring performance, please wait"); > + fflush(stdout); > + ut_params.entries = 1 << 20; > + ut_params.name = "test_average_utilization"; > + ut_params.hash_func = rte_jhash; > + handle = rte_hash_create(&ut_params); > + RETURN_IF_ERROR(handle == NULL, "hash creation failed"); > + > + for (j = 0; j < ITERATIONS; j++) { > + ret = 0; > + /* Add random entries until key cannot be added */ > + for (added_keys = 0; ret >= 0; added_keys++) { > + for (i = 0; i < ut_params.key_len; i++) > + simple_key[i] = rte_rand() % 255; > + ret = rte_hash_add_key(handle, simple_key); > + } > + if (ret != -ENOSPC) { > + printf("Unexpected error when adding keys\n"); > + rte_hash_free(handle); > + return -1; > + } > + > + average_keys_added += added_keys; > + > + /* Reset the table */ > + rte_hash_free(handle); > + handle = rte_hash_create(&ut_params); > + RETURN_IF_ERROR(handle == NULL, "hash creation failed"); > + > + /* Print a dot to show progress on operations */ > + printf("."); > + fflush(stdout); > + } > + > + average_keys_added /= ITERATIONS; > + > + printf("\nAverage table utilization = %.2f%% (%u/%u)\n", > + ((double) average_keys_added / ut_params.entries * 100), > + average_keys_added, ut_params.entries); > + rte_hash_free(handle); > + > + return 0; > +} > + > static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03, > 0x04, 0x05, 0x06, 0x07, > 0x08, 0x09, 0x0a, 0x0b, > @@ -1405,6 +1465,8 @@ test_hash(void) > return -1; > if (test_hash_creation_with_good_parameters() < 0) > return -1; > + if (test_average_table_utilization() < 0) > + return -1; > > run_hash_func_tests(); > > diff --git a/app/test/test_hash_perf.c b/app/test/test_hash_perf.c > index d0e5ce0..a3876c1 100644 > --- a/app/test/test_hash_perf.c > +++ b/app/test/test_hash_perf.c > @@ -32,574 +32,436 @@ > */ > > #include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > +#include > + > #include > -#include > #include > +#include > +#include > +#include > +#include > +#include > #include > -#include > -#include > -#include > -#include > #include > > #include "test.h" > > -#include > -#include > -#include > -#include > - > -/* Types of hash table performance test that can be performed */ > -enum hash_test_t { > - ADD_ON_EMPTY, /*< Add keys to empty table */ > - DELETE_ON_EMPTY, /*< Attempt to delete keys from empty table */ > - LOOKUP_ON_EMPTY, /*< Attempt to find keys in an empty table */ > - ADD_UPDATE, /*< Add/update keys in a full table */ > - DELETE, /*< Delete keys from a full table */ > - LOOKUP /*< Find keys in a full table */ > +#define MAX_ENTRIES (1 << 19) > +#define KEYS_TO_ADD (MAX_ENTRIES * 3 / 4) /* 75% table utilization */ > +#define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */ > +#define BUCKET_SIZE 4 > +#define NUM_BUCKETS (MAX_ENTRIES / BUCKET_SIZE) > +#define MAX_KEYSIZE 64 > +#define NUM_KEYSIZES 10 > +#define NUM_SHUFFLES 10 > +#define BURST_SIZE 16 > + > +enum operations { > + ADD = 0, > + LOOKUP, > + LOOKUP_MULTI, > + DELETE, > + NUM_OPERATIONS > }; > > -/* Function type for hash table operations. */ > -typedef int32_t (*hash_operation)(const struct rte_hash *h, const void *key); > - > -/* Structure to hold parameters used to run a hash table performance test */ > -struct tbl_perf_test_params { > - enum hash_test_t test_type; > - uint32_t num_iterations; > - uint32_t entries; > - uint32_t bucket_entries; > - uint32_t key_len; > - rte_hash_function hash_func; > - uint32_t hash_func_init_val; > +static uint32_t hashtest_key_lens[] = { > + /* standard key sizes */ > + 4, 8, 16, 32, 48, 64, > + /* IPv4 SRC + DST + protocol, unpadded */ > + 9, > + /* IPv4 5-tuple, unpadded */ > + 13, > + /* IPv6 5-tuple, unpadded */ > + 37, > + /* IPv6 5-tuple, padded to 8-byte boundary */ > + 40 > }; > > -#define ITERATIONS 10000 > -#define LOCAL_FBK_HASH_ENTRIES_MAX (1 << 15) > +struct rte_hash *h[NUM_KEYSIZES]; > > -/******************************************************************************* > - * Hash table performance test configuration section. > - */ > -struct tbl_perf_test_params tbl_perf_params[] = > -{ > -/* Small table, add */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_ON_EMPTY, 1024, 1024, 1, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 1, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 1, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 1, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 64, rte_jhash, 0}, > -/* Small table, update */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 64, rte_jhash, 0}, > -/* Small table, lookup */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ LOOKUP, ITERATIONS, 1024, 1, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 1, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 1, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 1, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 64, rte_jhash, 0}, > -/* Big table, add */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 16, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 32, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 48, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 64, rte_jhash, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 64, rte_jhash, 0}, > -/* Big table, update */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 16, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 32, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 48, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 64, rte_jhash, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 64, rte_jhash, 0}, > -/* Big table, lookup */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ LOOKUP, ITERATIONS, 1048576, 1, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 16, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 1, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 32, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 1, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 48, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 1, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 64, rte_jhash, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 64, rte_jhash, 0}, > -/* Small table, add */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_ON_EMPTY, 1024, 1024, 1, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 1, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 1, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 1, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 2, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 4, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 8, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1024, 1024, 16, 64, rte_hash_crc, 0}, > -/* Small table, update */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 1, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 2, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 4, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 8, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1024, 16, 64, rte_hash_crc, 0}, > -/* Small table, lookup */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ LOOKUP, ITERATIONS, 1024, 1, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 1, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 1, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 1, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 2, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 4, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 8, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1024, 16, 64, rte_hash_crc, 0}, > -/* Big table, add */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 16, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 32, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 48, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 1, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 2, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 4, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 8, 64, rte_hash_crc, 0}, > -{ ADD_ON_EMPTY, 1048576, 1048576, 16, 64, rte_hash_crc, 0}, > -/* Big table, update */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 16, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 32, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 48, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 1, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 2, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 4, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 8, 64, rte_hash_crc, 0}, > -{ ADD_UPDATE, ITERATIONS, 1048576, 16, 64, rte_hash_crc, 0}, > -/* Big table, lookup */ > -/* Test type | Iterations | Entries | BucketSize | KeyLen | HashFunc | InitVal */ > -{ LOOKUP, ITERATIONS, 1048576, 1, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 16, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 1, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 32, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 1, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 48, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 1, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 2, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 4, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 8, 64, rte_hash_crc, 0}, > -{ LOOKUP, ITERATIONS, 1048576, 16, 64, rte_hash_crc, 0}, > -}; > +/* Array that stores if a slot is full */ > +uint8_t slot_taken[MAX_ENTRIES]; > > -/******************************************************************************/ > +/* Array to store number of cycles per operation */ > +uint64_t cycles[NUM_KEYSIZES][NUM_OPERATIONS][2]; > > -/* > - * Check condition and return an error if true. Assumes that "handle" is the > - * name of the hash structure pointer to be freed. > - */ > -#define RETURN_IF_ERROR(cond, str, ...) do { \ > - if (cond) { \ > - printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ > - if (handle) rte_hash_free(handle); \ > - return -1; \ > - } \ > -} while(0) > - > -#define RETURN_IF_ERROR_FBK(cond, str, ...) do { \ > - if (cond) { \ > - printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \ > - if (handle) rte_fbk_hash_free(handle); \ > - rte_free(keys); \ > - return -1; \ > - } \ > -} while(0) > +/* Array to store all input keys */ > +uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE]; > > -/* > - * Find average of array of numbers. > - */ > -static double > -get_avg(const uint32_t *array, uint32_t size) > +/* Array to store the precomputed hash for 'keys' */ > +hash_sig_t signatures[KEYS_TO_ADD]; > + > +/* Array to store how many busy entries have each bucket */ > +uint8_t buckets[NUM_BUCKETS]; > + > +/* Array to store the positions where keys are added */ > +int32_t positions[KEYS_TO_ADD]; > + > +/* Parameters used for hash table in unit test functions. */ > +static struct rte_hash_parameters ut_params = { > + .entries = MAX_ENTRIES, > + .bucket_entries = BUCKET_SIZE, > + .hash_func = rte_jhash, > + .hash_func_init_val = 0, > +}; > + > +static int > +create_table(unsigned table_index) > { > - double sum = 0; > - unsigned i; > - for (i = 0; i < size; i++) > - sum += array[i]; > - return sum / (double)size; > + char name[RTE_HASH_NAMESIZE]; > + > + sprintf(name, "test_hash%d", hashtest_key_lens[table_index]); > + ut_params.name = name; > + ut_params.key_len = hashtest_key_lens[table_index]; > + ut_params.socket_id = rte_socket_id(); > + h[table_index] = rte_hash_find_existing(name); > + if (h[table_index] != NULL) > + /* > + * If table was already created, free it to create it again, > + * so we force it is empty > + */ > + rte_hash_free(h[table_index]); > + h[table_index] = rte_hash_create(&ut_params); > + if (h[table_index] == NULL) { > + printf("Error creating table\n"); > + return -1; > + } > + return 0; > + > } > > -/* > - * To help print out name of hash functions. > - */ > -static const char *get_hash_name(rte_hash_function f) > +/* Shuffle the keys that have been added, so lookups will be totally random */ > +static void > +shuffle_input_keys(unsigned table_index) > { > - if (f == rte_jhash) > - return "jhash"; > + unsigned i; > + uint32_t swap_idx; > + uint8_t temp_key[RTE_HASH_KEY_LENGTH_MAX]; > + hash_sig_t temp_signature; > + int32_t temp_position; > > - if (f == rte_hash_crc) > - return "rte_hash_crc"; > + for (i = KEYS_TO_ADD - 1; i > 0; i--) { > + swap_idx = rte_rand() % i; > > - return "UnknownHash"; > + memcpy(temp_key, keys[i], hashtest_key_lens[table_index]); > + temp_signature = signatures[i]; > + temp_position = positions[i]; > + > + memcpy(keys[i], keys[swap_idx], hashtest_key_lens[table_index]); > + signatures[i] = signatures[swap_idx]; > + positions[i] = positions[swap_idx]; > + > + memcpy(keys[swap_idx], temp_key, hashtest_key_lens[table_index]); > + signatures[swap_idx] = temp_signature; > + positions[swap_idx] = temp_position; > + } > } > > /* > - * Do a single performance test, of one type of operation. > - * > - * @param h > - * hash table to run test on > - * @param func > - * function to call (add, delete or lookup function) > - * @param avg_occupancy > - * The average number of entries in each bucket of the hash table > - * @param invalid_pos_count > - * The amount of errors (e.g. due to a full bucket). > - * @return > - * The average number of ticks per hash function call. A negative number > - * signifies failure. > + * Looks for random keys which > + * ALL can fit in hash table (no errors) > */ > -static double > -run_single_tbl_perf_test(const struct rte_hash *h, hash_operation func, > - const struct tbl_perf_test_params *params, double *avg_occupancy, > - uint32_t *invalid_pos_count) > +static int > +get_input_keys(unsigned table_index) > { > - uint64_t begin, end, ticks = 0; > - uint8_t *key = NULL; > - uint32_t *bucket_occupancies = NULL; > - uint32_t num_buckets, i, j; > - int32_t pos; > - > - /* Initialise */ > - num_buckets = params->entries / params->bucket_entries; > - key = rte_zmalloc("hash key", > - params->key_len * sizeof(uint8_t), 16); > - if (key == NULL) > - return -1; > + unsigned i, j; > + unsigned bucket_idx, incr, success = 1; > + uint8_t k = 0; > + int32_t ret; > + const uint32_t bucket_bitmask = NUM_BUCKETS - 1; > > - bucket_occupancies = rte_calloc("bucket occupancies", > - num_buckets, sizeof(uint32_t), 16); > - if (bucket_occupancies == NULL) { > - rte_free(key); > - return -1; > - } > + /* Reset all arrays */ > + for (i = 0; i < MAX_ENTRIES; i++) > + slot_taken[i] = 0; > > - ticks = 0; > - *invalid_pos_count = 0; > + for (i = 0; i < NUM_BUCKETS; i++) > + buckets[i] = 0; > > - for (i = 0; i < params->num_iterations; i++) { > - /* Prepare inputs for the current iteration */ > - for (j = 0; j < params->key_len; j++) > - key[j] = (uint8_t) rte_rand(); > + for (j = 0; j < hashtest_key_lens[table_index]; j++) > + keys[0][j] = 0; > > - /* Perform operation, and measure time it takes */ > - begin = rte_rdtsc(); > - pos = func(h, key); > - end = rte_rdtsc(); > - ticks += end - begin; > + /* > + * Add only entries that are not duplicated and that fits in the table > + * (cannot store more than BUCKET_SIZE entries in a bucket). > + * Regardless a key has been added correctly or not (success), > + * the next one to try will be increased by 1. > + */ > + for (i = 0; i < KEYS_TO_ADD;) { > + incr = 0; > + if (i != 0) { > + keys[i][0] = ++k; > + /* Overflow, need to increment the next byte */ > + if (keys[i][0] == 0) > + incr = 1; > + for (j = 1; j < hashtest_key_lens[table_index]; j++) { > + /* Do not increase next byte */ > + if (incr == 0) > + if (success == 1) > + keys[i][j] = keys[i - 1][j]; > + else > + keys[i][j] = keys[i][j]; > + /* Increase next byte by one */ > + else { > + if (success == 1) > + keys[i][j] = keys[i-1][j] + 1; > + else > + keys[i][j] = keys[i][j] + 1; > + if (keys[i][j] == 0) > + incr = 1; > + else > + incr = 0; > + } > + } > + } > + success = 0; > + signatures[i] = rte_hash_hash(h[table_index], keys[i]); > + bucket_idx = signatures[i] & bucket_bitmask; > + /* If bucket is full, do not try to insert the key */ > + if (buckets[bucket_idx] == BUCKET_SIZE) > + continue; > + /* If key can be added, leave in successful key arrays "keys" */ > + ret = rte_hash_add_key_with_hash(h[table_index], keys[i], > + signatures[i]); > + if (ret >= 0) { > + /* If key is already added, ignore the entry and do not store */ > + if (slot_taken[ret]) > + continue; > + else { > + /* Store the returned position and mark slot as taken */ > + slot_taken[ret] = 1; > + buckets[bucket_idx]++; > + success = 1; > + i++; > + } > + } > + } > > - /* Other work per iteration */ > - if (pos < 0) > - *invalid_pos_count += 1; > + /* Reset the table, so we can measure the time to add all the entries */ > + rte_hash_free(h[table_index]); > + h[table_index] = rte_hash_create(&ut_params); > + > + return 0; > +} > + > +static int > +timed_adds(unsigned with_hash, unsigned table_index) > +{ > + unsigned i; > + const uint64_t start_tsc = rte_rdtsc(); > + int32_t ret; > + > + for (i = 0; i < KEYS_TO_ADD; i++) { > + if (with_hash) > + ret = rte_hash_add_key_with_hash(h[table_index], > + (const void *) keys[i], > + signatures[i]); > else > - bucket_occupancies[pos / params->bucket_entries]++; > + ret = rte_hash_add_key(h[table_index], keys[i]); > + > + if (ret >= 0) > + positions[i] = ret; > + else { > + printf("Failed to add key number %u\n", ret); > + return -1; > + } > } > - *avg_occupancy = get_avg(bucket_occupancies, num_buckets); > > - rte_free(bucket_occupancies); > - rte_free(key); > + const uint64_t end_tsc = rte_rdtsc(); > + const uint64_t time_taken = end_tsc - start_tsc; > > - return (double)ticks / params->num_iterations; > + cycles[table_index][ADD][with_hash] = time_taken/KEYS_TO_ADD; > + return 0; > } > > -/* > - * To help print out what tests are being done. > - */ > -static const char * > -get_tbl_perf_test_desc(enum hash_test_t type) > +static int > +timed_lookups(unsigned with_hash, unsigned table_index) > { > - switch (type){ > - case ADD_ON_EMPTY: return "Add on Empty"; > - case DELETE_ON_EMPTY: return "Delete on Empty"; > - case LOOKUP_ON_EMPTY: return "Lookup on Empty"; > - case ADD_UPDATE: return "Add Update"; > - case DELETE: return "Delete"; > - case LOOKUP: return "Lookup"; > - default: return "UNKNOWN"; > + unsigned i, j; > + const uint64_t start_tsc = rte_rdtsc(); > + int32_t ret; > + > + for (i = 0; i < NUM_LOOKUPS/KEYS_TO_ADD; i++) { > + for (j = 0; j < KEYS_TO_ADD; j++) { > + if (with_hash) > + ret = rte_hash_lookup_with_hash(h[table_index], > + (const void *) keys[j], > + signatures[j]); > + else > + ret = rte_hash_lookup(h[table_index], keys[j]); > + if (ret < 0 || ret != positions[j]) { > + printf("Key looked up in %d, should be in %d\n", > + ret, positions[j]); > + return -1; > + } > + } > } > + > + const uint64_t end_tsc = rte_rdtsc(); > + const uint64_t time_taken = end_tsc - start_tsc; > + > + cycles[table_index][LOOKUP][with_hash] = time_taken/NUM_LOOKUPS; > + > + return 0; > } > > -/* > - * Run a hash table performance test based on params. > - */ > static int > -run_tbl_perf_test(struct tbl_perf_test_params *params) > +timed_lookups_multi(unsigned table_index) > { > - static unsigned calledCount = 5; > - struct rte_hash_parameters hash_params = { > - .entries = params->entries, > - .bucket_entries = params->bucket_entries, > - .key_len = params->key_len, > - .hash_func = params->hash_func, > - .hash_func_init_val = params->hash_func_init_val, > - .socket_id = rte_socket_id(), > - }; > - struct rte_hash *handle; > - double avg_occupancy = 0, ticks = 0; > - uint32_t num_iterations, invalid_pos; > - char name[RTE_HASH_NAMESIZE]; > - char hashname[RTE_HASH_NAMESIZE]; > - > - snprintf(name, 32, "test%u", calledCount++); > - hash_params.name = name; > - > - handle = rte_hash_create(&hash_params); > - RETURN_IF_ERROR(handle == NULL, "hash creation failed"); > - > - switch (params->test_type){ > - case ADD_ON_EMPTY: > - ticks = run_single_tbl_perf_test(handle, rte_hash_add_key, > - params, &avg_occupancy, &invalid_pos); > - break; > - case DELETE_ON_EMPTY: > - ticks = run_single_tbl_perf_test(handle, rte_hash_del_key, > - params, &avg_occupancy, &invalid_pos); > - break; > - case LOOKUP_ON_EMPTY: > - ticks = run_single_tbl_perf_test(handle, rte_hash_lookup, > - params, &avg_occupancy, &invalid_pos); > - break; > - case ADD_UPDATE: > - num_iterations = params->num_iterations; > - params->num_iterations = params->entries; > - run_single_tbl_perf_test(handle, rte_hash_add_key, params, > - &avg_occupancy, &invalid_pos); > - params->num_iterations = num_iterations; > - ticks = run_single_tbl_perf_test(handle, rte_hash_add_key, > - params, &avg_occupancy, &invalid_pos); > - break; > - case DELETE: > - num_iterations = params->num_iterations; > - params->num_iterations = params->entries; > - run_single_tbl_perf_test(handle, rte_hash_add_key, params, > - &avg_occupancy, &invalid_pos); > - > - params->num_iterations = num_iterations; > - ticks = run_single_tbl_perf_test(handle, rte_hash_del_key, > - params, &avg_occupancy, &invalid_pos); > - break; > - case LOOKUP: > - num_iterations = params->num_iterations; > - params->num_iterations = params->entries; > - run_single_tbl_perf_test(handle, rte_hash_add_key, params, > - &avg_occupancy, &invalid_pos); > - > - params->num_iterations = num_iterations; > - ticks = run_single_tbl_perf_test(handle, rte_hash_lookup, > - params, &avg_occupancy, &invalid_pos); > - break; > - default: return -1; > + unsigned i, j, k; > + int32_t positions_burst[BURST_SIZE]; > + const void *keys_burst[BURST_SIZE]; > + const uint64_t start_tsc = rte_rdtsc(); > + > + for (i = 0; i < NUM_LOOKUPS/KEYS_TO_ADD; i++) { > + for (j = 0; j < KEYS_TO_ADD/BURST_SIZE; j++) { > + for (k = 0; k < BURST_SIZE; k++) > + keys_burst[k] = keys[j * BURST_SIZE + k]; > + > + rte_hash_lookup_bulk(h[table_index], > + (const void **) keys_burst, > + BURST_SIZE, > + positions_burst); > + for (k = 0; k < BURST_SIZE; k++) { > + if (positions_burst[k] != positions[j * BURST_SIZE + k]) { > + printf("Key looked up in %d, should be in %d\n", > + positions_burst[k], > + positions[j * BURST_SIZE + k]); > + return -1; > + } > + } > + } > } > > - snprintf(hashname, RTE_HASH_NAMESIZE, "%s", get_hash_name(params->hash_func)); > - > - printf("%-12s, %-15s, %-16u, %-7u, %-18u, %-8u, %-19.2f, %.2f\n", > - hashname, > - get_tbl_perf_test_desc(params->test_type), > - (unsigned) params->key_len, > - (unsigned) params->entries, > - (unsigned) params->bucket_entries, > - (unsigned) invalid_pos, > - avg_occupancy, > - ticks > - ); > - > - /* Free */ > - rte_hash_free(handle); > + const uint64_t end_tsc = rte_rdtsc(); > + const uint64_t time_taken = end_tsc - start_tsc; > + > + cycles[table_index][LOOKUP_MULTI][0] = time_taken/NUM_LOOKUPS; > + > return 0; > } > > -/* > - * Run all hash table performance tests. > - */ > -static int run_all_tbl_perf_tests(void) > +static int > +timed_deletes(unsigned with_hash, unsigned table_index) > { > unsigned i; > + const uint64_t start_tsc = rte_rdtsc(); > + int32_t ret; > + > + for (i = 0; i < KEYS_TO_ADD; i++) { > + if (with_hash) > + ret = rte_hash_del_key_with_hash(h[table_index], > + (const void *) keys[i], > + signatures[i]); > + else > + ret = rte_hash_del_key(h[table_index], > + (const void *) keys[i]); > + if (ret >= 0) > + positions[i] = ret; > + else { > + printf("Failed to add key number %u\n", ret); > + return -1; > + } > + } > + > + const uint64_t end_tsc = rte_rdtsc(); > + const uint64_t time_taken = end_tsc - start_tsc; > + > + cycles[table_index][DELETE][with_hash] = time_taken/KEYS_TO_ADD; > + > + return 0; > +} > + > +static void > +free_table(unsigned table_index) > +{ > + rte_hash_free(h[table_index]); > +} > + > +static int > +reset_table(unsigned table_index) > +{ > + free_table(table_index); > + if (create_table(table_index) != 0) > + return -1; > + > + return 0; > +} > + > +static int > +run_all_tbl_perf_tests(void) > +{ > + unsigned i, j; > > - printf(" *** Hash table performance test results ***\n"); > - printf("Hash Func. , Operation , Key size (bytes), Entries, " > - "Entries per bucket, Errors , Avg. bucket entries, Ticks/Op.\n"); > + printf("Measuring performance, please wait"); > + fflush(stdout); > + for (i = 0; i < NUM_KEYSIZES; i++) { > + if (create_table(i) < 0) > + return -1; > + > + if (get_input_keys(i) < 0) > + return -1; > + > + if (timed_adds(0, i) < 0) > + return -1; > + > + for (j = 0; j < NUM_SHUFFLES; j++) > + shuffle_input_keys(i); > + > + if (timed_lookups(0, i) < 0) > + return -1; > + > + if (timed_lookups_multi(i) < 0) > + return -1; > + > + if (timed_deletes(0, i) < 0) > + return -1; > > - /* Loop through every combination of test parameters */ > - for (i = 0; > - i < sizeof(tbl_perf_params) / sizeof(struct tbl_perf_test_params); > - i++) { > + /* Print a dot to show progress on operations */ > + printf("."); > + fflush(stdout); > + > + if (reset_table(i) < 0) > + return -1; > > - /* Perform test */ > - if (run_tbl_perf_test(&tbl_perf_params[i]) < 0) > + if (timed_adds(1, i) < 0) > return -1; > + > + for (j = 0; j < NUM_SHUFFLES; j++) > + shuffle_input_keys(i); > + > + if (timed_lookups(1, i) < 0) > + return -1; > + > + if (timed_deletes(1, i) < 0) > + return -1; > + > + /* Print a dot to show progress on operations */ > + printf("."); > + fflush(stdout); > + > + free_table(i); > + } > + printf("\nResults (in CPU cycles/operation)\n"); > + printf("---------------------------------\n"); > + printf("\nWithout pre-computed hash values\n"); > + printf("\n%-18s%-18s%-18s%-18s%-18s\n", > + "Keysize", "Add", "Lookup", "Lookup_bulk", "Delete"); > + for (i = 0; i < NUM_KEYSIZES; i++) { > + printf("%-18d", hashtest_key_lens[i]); > + for (j = 0; j < NUM_OPERATIONS; j++) > + printf("%-18"PRIu64, cycles[i][j][0]); > + printf("\n"); > + } > + printf("\nWith pre-computed hash values\n"); > + printf("\n%-18s%-18s%-18s%-18s%-18s\n", > + "Keysize", "Add", "Lookup", "Lookup_bulk", "Delete"); > + for (i = 0; i < NUM_KEYSIZES; i++) { > + printf("%-18d", hashtest_key_lens[i]); > + for (j = 0; j < NUM_OPERATIONS; j++) > + printf("%-18"PRIu64, cycles[i][j][1]); > + printf("\n"); > } > + > return 0; > } > > @@ -624,28 +486,34 @@ fbk_hash_perf_test(void) > uint64_t lookup_time = 0; > unsigned added = 0; > unsigned value = 0; > + uint32_t key; > + uint16_t val; > unsigned i, j; > > handle = rte_fbk_hash_create(¶ms); > - RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed"); > + if (handle == NULL) { > + printf("Error creating table\n"); > + return -1; > + } > > keys = rte_zmalloc(NULL, ENTRIES * sizeof(*keys), 0); > - RETURN_IF_ERROR_FBK(keys == NULL, > - "fbk hash: memory allocation for key store failed"); > + if (keys == NULL) { > + printf("fbk hash: memory allocation for key store failed\n"); > + return -1; > + } > > /* Generate random keys and values. */ > for (i = 0; i < ENTRIES; i++) { > - uint32_t key = (uint32_t)rte_rand(); > + key = (uint32_t)rte_rand(); > key = ((uint64_t)key << 32) | (uint64_t)rte_rand(); > - uint16_t val = (uint16_t)rte_rand(); > + val = (uint16_t)rte_rand(); > > if (rte_fbk_hash_add_key(handle, key, val) == 0) { > keys[added] = key; > added++; > } > - if (added > (LOAD_FACTOR * ENTRIES)) { > + if (added > (LOAD_FACTOR * ENTRIES)) > break; > - } > } > > for (i = 0; i < TEST_ITERATIONS; i++) { > @@ -653,15 +521,14 @@ fbk_hash_perf_test(void) > uint64_t end; > > /* Generate random indexes into keys[] array. */ > - for (j = 0; j < TEST_SIZE; j++) { > + for (j = 0; j < TEST_SIZE; j++) > indexes[j] = rte_rand() % added; > - } > > begin = rte_rdtsc(); > /* Do lookups */ > - for (j = 0; j < TEST_SIZE; j++) { > + for (j = 0; j < TEST_SIZE; j++) > value += rte_fbk_hash_lookup(handle, keys[indexes[j]]); > - } > + > end = rte_rdtsc(); > lookup_time += (double)(end - begin); > } > @@ -681,9 +548,6 @@ fbk_hash_perf_test(void) > return 0; > } > > -/* > - * Do all unit and performance tests. > - */ > static int > test_hash_perf(void) > { > @@ -692,11 +556,12 @@ test_hash_perf(void) > > if (fbk_hash_perf_test() < 0) > return -1; > + > return 0; > } > > static struct test_command hash_perf_cmd = { > - .command = "hash_perf_autotest", > - .callback = test_hash_perf, > + .command = "hash_perf_autotest", > + .callback = test_hash_perf, > }; > REGISTER_TEST_COMMAND(hash_perf_cmd); > -- > 2.4.2 >