summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/asn1Decoding.c108
-rw-r--r--src/benchmark.c157
-rw-r--r--src/benchmark.h52
-rw-r--r--tests/Makefile.am2
-rwxr-xr-xtests/benchmark35
6 files changed, 316 insertions, 40 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3080c40..b0ed06e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,4 +27,4 @@ asn1Parser_SOURCES = asn1Parser.c
asn1Coding_SOURCES = asn1Coding.c
-asn1Decoding_SOURCES = asn1Decoding.c
+asn1Decoding_SOURCES = asn1Decoding.c benchmark.c benchmark.h
diff --git a/src/asn1Decoding.c b/src/asn1Decoding.c
index 2fa97a9..494f14b 100644
--- a/src/asn1Decoding.c
+++ b/src/asn1Decoding.c
@@ -31,6 +31,9 @@
#include <progname.h>
#include <version-etc.h>
#include <read-file.h>
+#include "benchmark.h"
+
+static int decode(ASN1_TYPE definitions, const char* typeName, void* der, int der_len, int benchmark);
/* This feature is available in gcc versions 2.5 and later. */
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
@@ -74,11 +77,10 @@ main (int argc, char *argv[])
char *inputFileDerName = NULL;
char *typeName = NULL;
ASN1_TYPE definitions = ASN1_TYPE_EMPTY;
- ASN1_TYPE structure = ASN1_TYPE_EMPTY;
char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
int asn1_result = ASN1_SUCCESS;
unsigned char *der;
- int der_len = 0;
+ int der_len = 0, benchmark = 0;
/* FILE *outputFile; */
set_program_name (argv[0]);
@@ -89,7 +91,7 @@ main (int argc, char *argv[])
{
option_result =
- getopt_long (argc, argv, "hvc", long_options, &option_index);
+ getopt_long (argc, argv, "hbvc", long_options, &option_index);
if (option_result == -1)
break;
@@ -99,6 +101,9 @@ main (int argc, char *argv[])
case 'h': /* HELP */
usage (EXIT_SUCCESS);
break;
+ case 'b':
+ benchmark = 1;
+ break;
case 'v': /* VERSION */
version_etc (stdout, program_name, PACKAGE, VERSION,
"Fabio Fiorina", NULL);
@@ -195,50 +200,17 @@ main (int argc, char *argv[])
fclose(inputFile);
*/
- asn1_result = asn1_create_element (definitions, typeName, &structure);
-
- /* asn1_print_structure(stdout,structure,"",ASN1_PRINT_ALL); */
-
-
- if (asn1_result != ASN1_SUCCESS)
+ if (decode( definitions, typeName, der, der_len, benchmark) != ASN1_SUCCESS)
{
- printf ("Structure creation: %s\n", asn1_strerror (asn1_result));
asn1_delete_structure (&definitions);
-
free (inputFileAsnName);
free (inputFileDerName);
free (typeName);
free (der);
exit (1);
}
-
- asn1_result =
- asn1_der_decoding (&structure, der, der_len, errorDescription);
- printf ("\nDecoding: %s\n", asn1_strerror (asn1_result));
- if (asn1_result != ASN1_SUCCESS)
- printf ("asn1Decoding: %s\n", errorDescription);
-
- printf ("\nDECODING RESULT:\n");
- asn1_print_structure (stdout, structure, "", ASN1_PRINT_NAME_TYPE_VALUE);
-
- /*****************************************/
- /* ONLY FOR TEST */
- /*****************************************/
- /*
- der_len=10000;
- option_index=0;
- asn1_result=asn1_read_value(structure,"?2.content",der,&der_len);
- outputFile=fopen("encryptedData.p12","w");
- while(der_len>0){
- fprintf(outputFile,"%c",der[option_index]);
- der_len--;
- option_index++;
- }
- fclose(outputFile);
- */
-
+
asn1_delete_structure (&definitions);
- asn1_delete_structure (&structure);
free (der);
@@ -251,3 +223,63 @@ main (int argc, char *argv[])
exit (0);
}
+
+static int simple_decode(ASN1_TYPE definitions, const char* typeName, void* der, int der_len, int benchmark)
+{
+
+int asn1_result;
+ASN1_TYPE structure = ASN1_TYPE_EMPTY;
+char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+
+ asn1_result = asn1_create_element (definitions, typeName, &structure);
+
+ /* asn1_print_structure(stdout,structure,"",ASN1_PRINT_ALL); */
+
+
+ if (asn1_result != ASN1_SUCCESS)
+ {
+ printf ("Structure creation: %s\n", asn1_strerror (asn1_result));
+ return asn1_result;
+ }
+
+ asn1_result =
+ asn1_der_decoding (&structure, der, der_len, errorDescription);
+
+ if (!benchmark) printf ("\nDecoding: %s\n", asn1_strerror (asn1_result));
+ if (asn1_result != ASN1_SUCCESS)
+ {
+ printf ("asn1Decoding: %s\n", errorDescription);
+ return asn1_result;
+ }
+
+ if (!benchmark)
+ {
+ printf ("\nDECODING RESULT:\n");
+ asn1_print_structure (stdout, structure, "", ASN1_PRINT_NAME_TYPE_VALUE);
+ }
+ asn1_delete_structure (&structure);
+ return ASN1_SUCCESS;
+}
+
+static int decode(ASN1_TYPE definitions, const char* typeName, void* der, int der_len, int benchmark)
+{
+struct benchmark_st st;
+
+ if (benchmark == 0) return simple_decode(definitions, typeName, der, der_len, benchmark);
+ else
+ {
+ start_benchmark(&st);
+
+ do
+ {
+ simple_decode(definitions, typeName, der, der_len, benchmark);
+ st.size++;
+ }
+ while(benchmark_must_finish == 0);
+
+ stop_benchmark(&st, "structures");
+ fprintf(stdout, "\n");
+
+ }
+ return ASN1_SUCCESS;
+}
diff --git a/src/benchmark.c b/src/benchmark.c
new file mode 100644
index 0000000..8ab3f8c
--- /dev/null
+++ b/src/benchmark.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include "benchmark.h"
+
+int benchmark_must_finish = 0;
+
+#if defined(_WIN32)
+#include <windows.h>
+DWORD WINAPI
+alarm_handler (LPVOID lpParameter)
+{
+ HANDLE wtimer = *((HANDLE *) lpParameter);
+ WaitForSingleObject (wtimer, INFINITE);
+ benchmark_must_finish = 1;
+ return 0;
+}
+#else
+static void
+alarm_handler (int signo)
+{
+ benchmark_must_finish = 1;
+}
+#endif
+
+static void
+value2human (unsigned long bytes, double time, double *data, double *speed,
+ char *metric)
+{
+ if (bytes > 1000 && bytes < 1000 * 1000)
+ {
+ *data = ((double) bytes) / 1000;
+ *speed = *data / time;
+ strcpy (metric, "KB");
+ return;
+ }
+ else if (bytes >= 1000 * 1000 && bytes < 1000 * 1000 * 1000)
+ {
+ *data = ((double) bytes) / (1000 * 1000);
+ *speed = *data / time;
+ strcpy (metric, "MB");
+ return;
+ }
+ else if (bytes >= 1000 * 1000 * 1000)
+ {
+ *data = ((double) bytes) / (1000 * 1000 * 1000);
+ *speed = *data / time;
+ strcpy (metric, "GB");
+ return;
+ }
+ else
+ {
+ *data = (double) bytes;
+ *speed = *data / time;
+ strcpy (metric, "bytes");
+ return;
+ }
+}
+
+void start_benchmark(struct benchmark_st * st)
+{
+ memset(st, 0, sizeof(*st));
+#ifndef _WIN32
+ st->old_handler = signal (SIGALRM, alarm_handler);
+#endif
+ gettime (&st->start);
+ benchmark_must_finish = 0;
+
+#if defined(_WIN32)
+ st->wtimer = CreateWaitableTimer (NULL, TRUE, NULL);
+ if (st->wtimer == NULL)
+ {
+ fprintf (stderr, "error: CreateWaitableTimer %u\n", GetLastError ());
+ exit(1);
+ }
+ st->wthread = CreateThread (NULL, 0, alarm_handler, &st->wtimer, 0, NULL);
+ if (st->wthread == NULL)
+ {
+ fprintf (stderr, "error: CreateThread %u\n", GetLastError ());
+ exit(1);
+ }
+ st->alarm_timeout.QuadPart = (2) * 10000000;
+ if (SetWaitableTimer (st->wtimer, &st->alarm_timeout, 0, NULL, NULL, FALSE) == 0)
+ {
+ fprintf (stderr, "error: SetWaitableTimer %u\n", GetLastError ());
+ exit(1);
+ }
+#else
+ alarm (2);
+#endif
+
+}
+
+/* returns the elapsed time */
+double stop_benchmark(struct benchmark_st * st, const char* metric)
+{
+ double secs;
+ unsigned long lsecs;
+ struct timespec stop;
+ double dspeed, ddata;
+ char imetric[16];
+
+#if defined(_WIN32)
+ if (st->wtimer != NULL)
+ CloseHandle (st->wtimer);
+ if (st->wthread != NULL)
+ CloseHandle (st->wthread);
+#else
+ signal(SIGALRM, st->old_handler);
+#endif
+
+ gettime (&stop);
+
+ lsecs = (stop.tv_sec * 1000 + stop.tv_nsec / (1000 * 1000) -
+ (st->start.tv_sec * 1000 + st->start.tv_nsec / (1000 * 1000)));
+ secs = lsecs;
+ secs /= 1000;
+
+ if (metric == NULL)
+ { /* assume bytes/sec */
+ value2human (st->size, secs, &ddata, &dspeed, imetric);
+ printf (" Processed %.2f %s in %.2f secs: ", ddata, imetric, secs);
+ printf ("%.2f %s/sec\n", dspeed, imetric);
+ }
+ else
+ {
+ ddata = (double) st->size;
+ dspeed = ddata / secs;
+ printf (" Processed %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+ }
+
+ return secs;
+}
diff --git a/src/benchmark.h b/src/benchmark.h
new file mode 100644
index 0000000..e7d3386
--- /dev/null
+++ b/src/benchmark.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+#include "timespec.h" /* gnulib gettime */
+
+typedef void (*sighandler_t)(int);
+
+struct benchmark_st
+{
+ struct timespec start;
+ unsigned long size;
+ sighandler_t old_handler;
+#if defined(_WIN32)
+ HANDLE wtimer;
+ HANDLE wthread;
+ LARGE_INTEGER alarm_timeout;
+#endif
+};
+
+extern int benchmark_must_finish;
+
+void start_benchmark(struct benchmark_st * st);
+double stop_benchmark(struct benchmark_st * st, const char* metric);
+
+inline static unsigned int
+timespec_sub_ms (struct timespec *a, struct timespec *b)
+{
+ return (a->tv_sec * 1000 + a->tv_nsec / (1000 * 1000) -
+ (b->tv_sec * 1000 + b->tv_nsec / (1000 * 1000)));
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 61c8737..a7f8336 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -27,7 +27,7 @@ EXTRA_DIST = Test_parser.asn Test_tree.asn Test_tree_asn1_tab.c \
# For crlf.
EXTRA_DIST += crlf.cer
-dist_check_SCRIPTS = crlf
+dist_check_SCRIPTS = crlf benchmark
dist_check_SCRIPTS += threadsafety
diff --git a/tests/benchmark b/tests/benchmark
new file mode 100755
index 0000000..17a006a
--- /dev/null
+++ b/tests/benchmark
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+# Copyright (C) 2006-2012 Free Software Foundation, Inc.
+#
+# Author: Simon Josefsson
+#
+# This file is part of LIBTASN1.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set -e
+
+srcdir=${srcdir:-.}
+ASN1DECODING=../src/asn1Decoding${EXEEXT}
+
+# The crlf.cer file is a normal certificate which contains bytes 0x0A
+# (LF), 0x0D (CF), and 0xFF (EOF), all are known to cause failures
+# when using fopen/fgetc/fscanf on streams on some systems (read:
+# Windows).
+
+$ASN1DECODING \
+ -b $srcdir/../examples/pkix.asn \
+ $srcdir/crlf.cer \
+ PKIX1Implicit88.Certificate