Blame benchtests/bench-memmove-walk.c

Packit 6c4009
/* Measure memmove function combined throughput for different alignments.
Packit 6c4009
   Copyright (C) 2017-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* This microbenchmark measures the throughput of memmove for various sizes from
Packit 6c4009
   1 byte to 32MiB, doubling every iteration and then misaligning by 0-15
Packit 6c4009
   bytes.  The copies are done from source to destination and then back and the
Packit 6c4009
   source walks forward across the array and the destination walks backward by
Packit 6c4009
   one byte each, thus measuring misaligned accesses as well.  The idea is to
Packit 6c4009
   avoid caching effects by copying a different string and far enough from each
Packit 6c4009
   other, walking in different directions so that we can measure prefetcher
Packit 6c4009
   efficiency (software or hardware) more closely than with a loop copying the
Packit 6c4009
   same data over and over, which eventually only gives us L1 cache
Packit 6c4009
   performance.  */
Packit 6c4009
Packit 6c4009
#ifndef MEMMOVE_RESULT
Packit 6c4009
# define MEMMOVE_RESULT(dst, len) dst
Packit 6c4009
# define START_SIZE 128
Packit 6c4009
# define MIN_PAGE_SIZE (getpagesize () + 32 * 1024 * 1024)
Packit 6c4009
# define TEST_MAIN
Packit 6c4009
# define TEST_NAME "memmove"
Packit 6c4009
# define TIMEOUT (20 * 60)
Packit 6c4009
# include "bench-string.h"
Packit 6c4009
Packit 6c4009
IMPL (memmove, 1)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#include "json-lib.h"
Packit 6c4009
Packit 6c4009
typedef char *(*proto_t) (char *, const char *, size_t);
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
do_one_test (json_ctx_t *json_ctx, impl_t *impl, char *dst, char *src,
Packit 6c4009
	     size_t len)
Packit 6c4009
{
Packit 6c4009
  size_t i = 0;
Packit 6c4009
  timing_t start, stop, cur;
Packit 6c4009
Packit 6c4009
  char *dst_end = dst + MIN_PAGE_SIZE - len;
Packit 6c4009
  char *src_end = src + MIN_PAGE_SIZE - len;
Packit 6c4009
Packit 6c4009
  TIMING_NOW (start);
Packit 6c4009
  /* Copy the entire buffer backwards, LEN at a time.  */
Packit 6c4009
  for (; src_end >= src && dst <= dst_end; dst += len, src_end -= len, i++)
Packit 6c4009
    CALL (impl, dst, src_end, len);
Packit 6c4009
  TIMING_NOW (stop);
Packit 6c4009
Packit 6c4009
  TIMING_DIFF (cur, start, stop);
Packit 6c4009
Packit 6c4009
  /* Get time taken per function call.  */
Packit 6c4009
  json_element_double (json_ctx, (double) cur / i);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
do_test (json_ctx_t *json_ctx, size_t len, bool overlap)
Packit 6c4009
{
Packit 6c4009
  json_element_object_begin (json_ctx);
Packit 6c4009
  json_attr_uint (json_ctx, "length", (double) len);
Packit 6c4009
  json_array_begin (json_ctx, "timings");
Packit 6c4009
Packit 6c4009
  if (overlap)
Packit 6c4009
    buf2 = buf1;
Packit 6c4009
Packit 6c4009
  FOR_EACH_IMPL (impl, 0)
Packit 6c4009
    do_one_test (json_ctx, impl, (char *) buf2, (char *) buf1, len);
Packit 6c4009
Packit 6c4009
  json_array_end (json_ctx);
Packit 6c4009
  json_element_object_end (json_ctx);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
test_main (void)
Packit 6c4009
{
Packit 6c4009
  json_ctx_t json_ctx;
Packit 6c4009
Packit 6c4009
  test_init ();
Packit 6c4009
Packit 6c4009
  json_init (&json_ctx, 0, stdout);
Packit 6c4009
Packit 6c4009
  json_document_begin (&json_ctx);
Packit 6c4009
  json_attr_string (&json_ctx, "timing_type", TIMING_TYPE);
Packit 6c4009
Packit 6c4009
  json_attr_object_begin (&json_ctx, "functions");
Packit 6c4009
  json_attr_object_begin (&json_ctx, "memmove");
Packit 6c4009
  json_attr_string (&json_ctx, "bench-variant", "walk");
Packit 6c4009
Packit 6c4009
  json_array_begin (&json_ctx, "ifuncs");
Packit 6c4009
  FOR_EACH_IMPL (impl, 0)
Packit 6c4009
    json_element_string (&json_ctx, impl->name);
Packit 6c4009
  json_array_end (&json_ctx);
Packit 6c4009
Packit 6c4009
  json_array_begin (&json_ctx, "results");
Packit 6c4009
  /* Non-overlapping buffers.  */
Packit 6c4009
  for (size_t i = START_SIZE; i <= MIN_PAGE_SIZE; i <<= 1)
Packit 6c4009
    {
Packit 6c4009
      /* Test length alignments from 0-16 bytes.  */
Packit 6c4009
      for (int j = 0; j < 8; j++)
Packit 6c4009
	{
Packit 6c4009
	  do_test (&json_ctx, i + j, false);
Packit 6c4009
	  do_test (&json_ctx, i + 16 - j, false);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Overlapping buffers.  */
Packit 6c4009
  for (size_t i = START_SIZE; i <= MIN_PAGE_SIZE; i <<= 1)
Packit 6c4009
    {
Packit 6c4009
      /* Test length alignments from 0-16 bytes.  */
Packit 6c4009
      for (int j = 0; j < 8; j++)
Packit 6c4009
	{
Packit 6c4009
	  do_test (&json_ctx, i + j, true);
Packit 6c4009
	  do_test (&json_ctx, i + 16 - j, true);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  json_array_end (&json_ctx);
Packit 6c4009
  json_attr_object_end (&json_ctx);
Packit 6c4009
  json_attr_object_end (&json_ctx);
Packit 6c4009
  json_document_end (&json_ctx);
Packit 6c4009
Packit 6c4009
  return ret;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include <support/test-driver.c>