mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-08 22:30:07 +00:00
Improve bench-memmem
Improve bench-memmem by replacing simple_memmem with a more efficient implementation. Add the Two-way implementation to enable direct comparison with the optimized memmem. * benchtests/bench-memmem.c (simple_memmem): Remove function. (basic_memmem): Add function. (twoway_memmem): Add function.
This commit is contained in:
parent
6103c0a811
commit
a173d09f85
@ -1,3 +1,9 @@
|
|||||||
|
2019-04-09 Wilco Dijkstra <wdijkstr@arm.com>
|
||||||
|
|
||||||
|
* benchtests/bench-memmem.c (simple_memmem): Remove function.
|
||||||
|
(basic_memmem): Add function.
|
||||||
|
(twoway_memmem): Add function.
|
||||||
|
|
||||||
2019-04-09 Wilco Dijkstra <wdijkstr@arm.com>
|
2019-04-09 Wilco Dijkstra <wdijkstr@arm.com>
|
||||||
|
|
||||||
* benchtests/bench-malloc-simple.c: Remove TIMING_INIT.
|
* benchtests/bench-malloc-simple.c: Remove TIMING_INIT.
|
||||||
|
@ -19,22 +19,51 @@
|
|||||||
#define TEST_MAIN
|
#define TEST_MAIN
|
||||||
#define TEST_NAME "memmem"
|
#define TEST_NAME "memmem"
|
||||||
#define BUF1PAGES 20
|
#define BUF1PAGES 20
|
||||||
#define ITERATIONS 500
|
#define ITERATIONS 100
|
||||||
#include "bench-string.h"
|
#include "bench-string.h"
|
||||||
|
|
||||||
typedef char *(*proto_t) (const void *, size_t, const void *, size_t);
|
typedef char *(*proto_t) (const void *, size_t, const void *, size_t);
|
||||||
void *simple_memmem (const void *, size_t, const void *, size_t);
|
|
||||||
|
|
||||||
IMPL (simple_memmem, 0)
|
|
||||||
IMPL (memmem, 1)
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
simple_memmem (const void *haystack, size_t haystack_len, const void *needle,
|
basic_memmem (const void *haystack, size_t hs_len, const void *needle,
|
||||||
size_t needle_len)
|
size_t ne_len)
|
||||||
{
|
{
|
||||||
const char *begin;
|
const char *hs = haystack;
|
||||||
const char *const last_possible
|
const char *ne = needle;
|
||||||
= (const char *) haystack + haystack_len - needle_len;
|
|
||||||
|
if (ne_len == 0)
|
||||||
|
return (void *)hs;
|
||||||
|
int i;
|
||||||
|
int c = ne[0];
|
||||||
|
const char *end = hs + hs_len - ne_len;
|
||||||
|
|
||||||
|
for ( ; hs <= end; hs++)
|
||||||
|
{
|
||||||
|
if (hs[0] != c)
|
||||||
|
continue;
|
||||||
|
for (i = ne_len - 1; i != 0; i--)
|
||||||
|
if (hs[i] != ne[i])
|
||||||
|
break;
|
||||||
|
if (i == 0)
|
||||||
|
return (void *)hs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RETURN_TYPE void *
|
||||||
|
#define AVAILABLE(h, h_l, j, n_l) ((j) <= (h_l) - (n_l))
|
||||||
|
#define FASTSEARCH(S,C,N) (void*) memchr ((void *)(S), (C), (N))
|
||||||
|
#include "../string/str-two-way.h"
|
||||||
|
|
||||||
|
void *
|
||||||
|
twoway_memmem (const void *haystack_start, size_t haystack_len,
|
||||||
|
const void *needle_start, size_t needle_len)
|
||||||
|
{
|
||||||
|
/* Abstract memory is considered to be an array of 'unsigned char' values,
|
||||||
|
not an array of 'char' values. See ISO C 99 section 6.2.6.1. */
|
||||||
|
const unsigned char *haystack = (const unsigned char *) haystack_start;
|
||||||
|
const unsigned char *needle = (const unsigned char *) needle_start;
|
||||||
|
|
||||||
if (needle_len == 0)
|
if (needle_len == 0)
|
||||||
/* The first occurrence of the empty string is deemed to occur at
|
/* The first occurrence of the empty string is deemed to occur at
|
||||||
@ -46,16 +75,32 @@ simple_memmem (const void *haystack, size_t haystack_len, const void *needle,
|
|||||||
if (__glibc_unlikely (haystack_len < needle_len))
|
if (__glibc_unlikely (haystack_len < needle_len))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (begin = (const char *) haystack; begin <= last_possible; ++begin)
|
/* Use optimizations in memchr when possible, to reduce the search
|
||||||
if (begin[0] == ((const char *) needle)[0]
|
size of haystack using a linear algorithm with a smaller
|
||||||
&& !memcmp ((const void *) &begin[1],
|
coefficient. However, avoid memchr for long needles, since we
|
||||||
(const void *) ((const char *) needle + 1),
|
can often achieve sublinear performance. */
|
||||||
needle_len - 1))
|
if (needle_len < LONG_NEEDLE_THRESHOLD)
|
||||||
return (void *) begin;
|
{
|
||||||
|
haystack = memchr (haystack, *needle, haystack_len);
|
||||||
return NULL;
|
if (!haystack || __builtin_expect (needle_len == 1, 0))
|
||||||
|
return (void *) haystack;
|
||||||
|
haystack_len -= haystack - (const unsigned char *) haystack_start;
|
||||||
|
if (haystack_len < needle_len)
|
||||||
|
return NULL;
|
||||||
|
/* Check whether we have a match. This improves performance since we
|
||||||
|
avoid the initialization overhead of the two-way algorithm. */
|
||||||
|
if (memcmp (haystack, needle, needle_len) == 0)
|
||||||
|
return (void *) haystack;
|
||||||
|
return two_way_short_needle (haystack, haystack_len, needle, needle_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return two_way_long_needle (haystack, haystack_len, needle, needle_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMPL (memmem, 1)
|
||||||
|
IMPL (twoway_memmem, 0)
|
||||||
|
IMPL (basic_memmem, 0)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_one_test (impl_t *impl, const void *haystack, size_t haystack_len,
|
do_one_test (impl_t *impl, const void *haystack, size_t haystack_len,
|
||||||
const void *needle, size_t needle_len, const void *expected)
|
const void *needle, size_t needle_len, const void *expected)
|
||||||
|
Loading…
Reference in New Issue
Block a user