summaryrefslogtreecommitdiffstats
path: root/debian/transcode/transcode-1.1.7/testsuite/test-acmemcpy-speed.c
diff options
context:
space:
mode:
Diffstat (limited to 'debian/transcode/transcode-1.1.7/testsuite/test-acmemcpy-speed.c')
-rw-r--r--debian/transcode/transcode-1.1.7/testsuite/test-acmemcpy-speed.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/testsuite/test-acmemcpy-speed.c b/debian/transcode/transcode-1.1.7/testsuite/test-acmemcpy-speed.c
new file mode 100644
index 00000000..dabef87f
--- /dev/null
+++ b/debian/transcode/transcode-1.1.7/testsuite/test-acmemcpy-speed.c
@@ -0,0 +1,279 @@
+/*compile-command
+set -x
+gcc -O3 -g -I. -I.. "$0" -DARCH_X86
+exit $?
+*/
+
+/*
+ * test-acmemcpy-speed.c - time all accelerated memcpy() implementations
+ * Written by Andrew Church <achurch@achurch.org>
+ *
+ * This file is part of transcode, a video stream processing tool.
+ * transcode is free software, distributable under the terms of the GNU
+ * General Public License (version 2 or later). See the file COPYING
+ * for details.
+ */
+
+#include "config.h"
+
+#define _GNU_SOURCE /* for strsignal */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+
+#define ac_memcpy local_ac_memcpy /* to avoid clash with libac.a */
+#define ac_memcpy_init local_ac_memcpy_init /* to avoid clash with libac.a */
+#include "aclib/ac.h"
+
+/* Include memcpy.c directly to get access to the particular implementations */
+#include "../aclib/memcpy.c"
+#undef ac_memcpy
+/* Make sure all names are available, to simplify function table */
+#if !defined(ARCH_X86) || !defined(HAVE_ASM_MMX)
+# define memcpy_mmx memcpy
+#endif
+#if !defined(ARCH_X86) || !defined(HAVE_ASM_SSE)
+# define memcpy_sse memcpy
+#endif
+#if !defined(ARCH_X86_64) || !defined(HAVE_ASM_SSE2)
+# define memcpy_amd64 memcpy
+#endif
+
+/* Default copy size and test length */
+#define DEF_BLOCKSIZE 0x10000
+#define DEF_TESTTIME 2000 /* milliseconds */
+
+/*************************************************************************/
+
+static void *old_SIGSEGV = NULL, *old_SIGILL = NULL, *old_SIGVTALRM = NULL;
+static sigjmp_buf env;
+
+
+static void sighandler(int sig)
+{
+ if (sig != SIGVTALRM)
+ printf("*** %s\n", strsignal(sig));
+ siglongjmp(env, sig);
+}
+
+static void set_signals(void)
+{
+ old_SIGSEGV = signal(SIGSEGV , sighandler);
+ old_SIGILL = signal(SIGILL , sighandler);
+ old_SIGVTALRM = signal(SIGVTALRM, sighandler);
+}
+
+static void clear_signals(void)
+{
+ signal(SIGSEGV , old_SIGSEGV );
+ signal(SIGILL , old_SIGILL );
+ signal(SIGVTALRM, old_SIGVTALRM);
+}
+
+/*************************************************************************/
+
+/* align1 and align2 are 0..63 */
+static void testit(void *(*func)(void *, const void *, size_t), int size,
+ int align1, int align2, int msec, uint64_t *iterations)
+{
+ char *chunk1, *chunk1_base;
+ char *chunk2, *chunk2_base;
+ int sig;
+ volatile uint64_t iter = 0;
+
+ chunk1_base = malloc(size+128);
+ chunk2_base = malloc(size+128);
+ chunk1 = (char *)(((long)chunk1_base+63) & -64) + align1;
+ chunk2 = (char *)(((long)chunk2_base+63) & -64) + align2;
+ memset(chunk1, 0x11, size);
+ memset(chunk2, 0x22, size);
+
+ set_signals();
+ if ((sig = sigsetjmp(env, 1)) != 0) {
+ if (sig == SIGVTALRM)
+ *iterations = iter;
+ else
+ *iterations = 0;
+ } else {
+ struct itimerval timer;
+
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 0;
+ timer.it_value.tv_sec = msec/1000;
+ timer.it_value.tv_usec = msec%1000;
+ if (setitimer(ITIMER_VIRTUAL, &timer, NULL) < 0) {
+ perror("setitimer");
+ exit(1);
+ }
+ for (;;) {
+ (*func)(chunk2, chunk1, size);
+ iter++;
+ }
+ }
+ clear_signals();
+
+ free(chunk1_base);
+ free(chunk2_base);
+}
+
+/*************************************************************************/
+
+/* Turn presence/absence of #define into a number */
+#if defined(ARCH_X86)
+# define defined_ARCH_X86 1
+#else
+# define defined_ARCH_X86 0
+#endif
+#if defined(ARCH_X86_64)
+# define defined_ARCH_X86_64 1
+#else
+# define defined_ARCH_X86_64 0
+#endif
+#if defined(HAVE_ASM_MMX)
+# define defined_HAVE_ASM_MMX 1
+#else
+# define defined_HAVE_ASM_MMX 0
+#endif
+#if defined(HAVE_ASM_SSE)
+# define defined_HAVE_ASM_SSE 1
+#else
+# define defined_HAVE_ASM_SSE 0
+#endif
+#if defined(HAVE_ASM_SSE2)
+# define defined_HAVE_ASM_SSE2 1
+#else
+# define defined_HAVE_ASM_SSE2 0
+#endif
+
+/* List of routines to test, NULL-terminated */
+static struct {
+ const char *name; /* centered in 5 chars */
+ int arch_ok; /* defined(ARCH_xxx) */
+ int acflags; /* required ac_cpuinfo() flags */
+ void *(*func)(void *, const void *, size_t);
+} testfuncs[] = {
+ { "libc ", 1,
+ 0, memcpy },
+ { " mmx ", defined_ARCH_X86 && defined_HAVE_ASM_MMX,
+ AC_MMX, memcpy_mmx },
+ { " sse ", defined_ARCH_X86 && defined_HAVE_ASM_SSE,
+ AC_CMOVE|AC_SSE, memcpy_sse },
+ { "amd64", defined_ARCH_X86_64 && defined_HAVE_ASM_SSE2,
+ AC_CMOVE|AC_SSE2, memcpy_amd64 },
+ { NULL }
+};
+
+/* Alignments/sizes to test */
+static struct {
+ int align1, align2;
+} tests[] = {
+ { 0, 0 },
+ { 0, 1 },
+ { 0, 4 },
+ { 0, 8 },
+ { 0, 63 },
+ { 1, 0 },
+ { 1, 1 },
+ { 1, 4 },
+ { 1, 8 },
+ { 1, 63 },
+ { 4, 0 },
+ { 4, 1 },
+ { 8, 0 },
+ { 8, 1 },
+ { 63, 0 },
+ { 63, 1 },
+ { 0, 0 },
+ { 0, 1 },
+ { 0, 4 },
+ { 0, 8 },
+ { 0, 63 },
+ { 1, 0 },
+ { 1, 1 },
+ { 1, 4 },
+ { 1, 8 },
+ { 1, 63 },
+ { -1, -1 }
+};
+
+int main(int argc, char *argv[])
+{
+ int size = DEF_BLOCKSIZE, testtime = DEF_TESTTIME;
+ int ch, i;
+
+ while ((ch = getopt(argc, argv, "hs:t:")) != EOF) {
+ if (ch == 's') {
+ size = atoi(optarg);
+ } else if (ch == 't') {
+ testtime = atoi(optarg);
+ } else {
+ usage:
+ fprintf(stderr,
+ "Usage: %s [-s blocksize] [-t msec-per-test]\n"
+ "Defaults: -s %d -t %d\n",
+ argv[0], DEF_BLOCKSIZE, DEF_TESTTIME);
+ return 1;
+ }
+ }
+ if (size <= 0 || testtime <= 0)
+ goto usage;
+
+ for (i = 0; testfuncs[i].name; i++) {
+ if ((ac_cpuinfo() & testfuncs[i].acflags) != testfuncs[i].acflags)
+ testfuncs[i].arch_ok = 0;
+ }
+
+ printf("Size: %d msec/test: %d Table entries in MB/s\n",
+ size, testtime);
+ printf("Align ");
+ for (i = 0; testfuncs[i].name; i++) {
+ if (testfuncs[i].arch_ok)
+ printf("|%s", testfuncs[i].name);
+ }
+ printf("\n------");
+ for (i = 0; testfuncs[i].name; i++) {
+ if (testfuncs[i].arch_ok)
+ printf("+-----");
+ }
+ printf("\n");
+
+ for (i = 0; tests[i].align1 >= 0; i++) {
+ int j;
+ printf("%2d/%2d ", tests[i].align1, tests[i].align2);
+ fflush(stdout);
+ for (j = 0; testfuncs[j].name; j++) {
+ if (testfuncs[j].arch_ok) {
+ uint64_t iterations;
+ testit(testfuncs[j].func, size,
+ tests[i].align1, tests[i].align2, testtime,
+ &iterations);
+ if (iterations == 0)
+ printf("|-ERR-");
+ else
+ printf("|%5d",
+ (int)(iterations*size*1000 / testtime / (1<<20)));
+ fflush(stdout);
+ }
+ }
+ printf("\n");
+ }
+ return 0;
+}
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ * c-file-style: "stroustrup"
+ * c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */