avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dcrea...@apache.org
Subject svn commit: r1145750 - in /avro/trunk/lang/c: ./ examples/ jansson/test/ jansson/test/testprogs/ src/ src/avro/ tests/
Date Tue, 12 Jul 2011 20:21:04 GMT
Author: dcreager
Date: Tue Jul 12 20:21:04 2011
New Revision: 1145750

URL: http://svn.apache.org/viewvc?rev=1145750&view=rev
Log:
AVO-746. C: Atomic reference counts

This patch updates all of the reference counts in various Avro objects
to be updated atomically.  This takes care of some race conditions when
Avro instances are passed between threads.  The atomic increment and
decrement operations are slower than the previous non-atomic operations,
but according to some basic performance tests, reference counting isn't
the dominating factor in the running time.

Added:
    avro/trunk/lang/c/examples/.gitignore
    avro/trunk/lang/c/jansson/test/.gitignore
    avro/trunk/lang/c/jansson/test/testprogs/.gitignore
    avro/trunk/lang/c/src/.gitignore
    avro/trunk/lang/c/src/avro/refcount.h
    avro/trunk/lang/c/tests/.gitignore
    avro/trunk/lang/c/tests/performance.c
Modified:
    avro/trunk/lang/c/.gitignore
    avro/trunk/lang/c/src/CMakeLists.txt
    avro/trunk/lang/c/src/Makefile.am
    avro/trunk/lang/c/src/avro.h
    avro/trunk/lang/c/src/datum.c
    avro/trunk/lang/c/src/io.c
    avro/trunk/lang/c/src/schema.c
    avro/trunk/lang/c/tests/CMakeLists.txt
    avro/trunk/lang/c/tests/Makefile.am

Modified: avro/trunk/lang/c/.gitignore
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/.gitignore?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/.gitignore (original)
+++ avro/trunk/lang/c/.gitignore Tue Jul 12 20:21:04 2011
@@ -1,10 +1,19 @@
+.deps
+.libs
+Makefile
 Makefile.in
 aclocal.m4
 autom4te.cache
+build
 config
+config.h
 config.h.in
+config.log
+config.status
 configure
-*.lo
+libtool
+stamp-h1
+*.l[ao]
 *.o
 INSTALL
 cscope.*

Added: avro/trunk/lang/c/examples/.gitignore
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/examples/.gitignore?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/examples/.gitignore (added)
+++ avro/trunk/lang/c/examples/.gitignore Tue Jul 12 20:21:04 2011
@@ -0,0 +1,2 @@
+quickstop
+quickstop.db

Added: avro/trunk/lang/c/jansson/test/.gitignore
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/jansson/test/.gitignore?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/jansson/test/.gitignore (added)
+++ avro/trunk/lang/c/jansson/test/.gitignore Tue Jul 12 20:21:04 2011
@@ -0,0 +1,9 @@
+bin/json_process
+suites/api/test_array
+suites/api/test_copy
+suites/api/test_dump
+suites/api/test_equal
+suites/api/test_load
+suites/api/test_number
+suites/api/test_object
+suites/api/test_simple

Added: avro/trunk/lang/c/jansson/test/testprogs/.gitignore
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/jansson/test/testprogs/.gitignore?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/jansson/test/testprogs/.gitignore (added)
+++ avro/trunk/lang/c/jansson/test/testprogs/.gitignore Tue Jul 12 20:21:04 2011
@@ -0,0 +1,5 @@
+test_array
+test_load
+test_number
+test_object
+test_simple

Added: avro/trunk/lang/c/src/.gitignore
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/.gitignore?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/src/.gitignore (added)
+++ avro/trunk/lang/c/src/.gitignore Tue Jul 12 20:21:04 2011
@@ -0,0 +1 @@
+avro-c.pc

Modified: avro/trunk/lang/c/src/CMakeLists.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/CMakeLists.txt?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/src/CMakeLists.txt (original)
+++ avro/trunk/lang/c/src/CMakeLists.txt Tue Jul 12 20:21:04 2011
@@ -22,6 +22,7 @@ set(AVRO_SRC
     allocation.c
     avro.h
     avro/consumer.h
+    avro/refcount.h
     avro_errors.h
     avro_private.h
     consumer.c
@@ -82,9 +83,10 @@ set_target_properties(avro-shared PROPER
 install(FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/avro.h
         DESTINATION include)
-install(FILES
-        ${CMAKE_CURRENT_SOURCE_DIR}/avro/consumer.h
-        DESTINATION include/avro)
+install(DIRECTORY
+        ${CMAKE_CURRENT_SOURCE_DIR}/avro
+        DESTINATION include
+        FILES_MATCHING PATTERN "*.h")
 install(TARGETS avro-static avro-shared
         RUNTIME DESTINATION bin
         LIBRARY DESTINATION lib

Modified: avro/trunk/lang/c/src/Makefile.am
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/Makefile.am?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/src/Makefile.am (original)
+++ avro/trunk/lang/c/src/Makefile.am Tue Jul 12 20:21:04 2011
@@ -6,7 +6,9 @@ ACLOCAL_AMFLAGS=-I m4
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = avro-c.pc
 
-nobase_include_HEADERS = avro.h avro/consumer.h
+nobase_include_HEADERS = avro.h \
+avro/consumer.h \
+avro/refcount.h
 
 lib_LTLIBRARIES = libavro.la
 libavro_la_SOURCES = st.c st.h schema.c schema.h schema_equal.c \

Modified: avro/trunk/lang/c/src/avro.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro.h?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/src/avro.h (original)
+++ avro/trunk/lang/c/src/avro.h Tue Jul 12 20:21:04 2011
@@ -84,7 +84,7 @@ typedef enum avro_class_t avro_class_t;
 struct avro_obj_t {
 	avro_type_t type;
 	avro_class_t class_type;
-	unsigned long refcount;
+	volatile int  refcount;
 };
 
 #define avro_classof(obj)     ((obj)->class_type)

Added: avro/trunk/lang/c/src/avro/refcount.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro/refcount.h?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/src/avro/refcount.h (added)
+++ avro/trunk/lang/c/src/avro/refcount.h Tue Jul 12 20:21:04 2011
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#ifndef AVRO_REFCOUNT_H
+#define AVRO_REFCOUNT_H
+#ifdef __cplusplus
+extern "C" {
+#define CLOSE_EXTERN }
+#else
+#define CLOSE_EXTERN
+#endif
+
+/**
+ * Atomically sets the value of a reference count.
+ */
+
+static inline void
+avro_refcount_set(volatile int *refcount, int value);
+
+/**
+ * Increments a reference count, ensuring that its value doesn't
+ * overflow.
+ */
+
+static inline void
+avro_refcount_inc(volatile int *refcount);
+
+/**
+ * Decrements a reference count, and returns whether the resulting
+ * (decremented) value is 0.
+ */
+
+static inline int
+avro_refcount_dec(volatile int *refcount);
+
+
+/*-----------------------------------------------------------------------
+ * Mac OS X
+ */
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
+
+#include <libkern/OSAtomic.h>
+
+static inline void
+avro_refcount_set(volatile int *refcount, int value)
+{
+	*refcount = value;
+}
+
+static inline void
+avro_refcount_inc(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		OSAtomicIncrement32(refcount);
+	}
+}
+
+static inline int
+avro_refcount_dec(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		return (OSAtomicDecrement32(refcount) == 0);
+	}
+	return 0;
+}
+
+
+/*-----------------------------------------------------------------------
+ * GCC intrinsics
+ */
+
+#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
+
+static inline void
+avro_refcount_set(volatile int *refcount, int value)
+{
+	*refcount = value;
+}
+
+static inline void
+avro_refcount_inc(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		__sync_add_and_fetch(refcount, 1);
+	}
+}
+
+static inline int
+avro_refcount_dec(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		return (__sync_sub_and_fetch(refcount, 1) == 0);
+	}
+	return 0;
+}
+
+
+/*-----------------------------------------------------------------------
+ * Raw x86 assembly
+ */
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+/* determine the size of int */
+
+#include <limits.h>
+#include <stdint.h>
+#if INT_MAX == INT32_MAX
+#define REFCOUNT_SS "l"
+#elif INT_MAX == INT64_MAX
+#define REFCOUNT_SS "q"
+#else
+#error "Unknown int size"
+#endif
+
+static inline void
+avro_refcount_set(volatile int *refcount, int value)
+{
+	*refcount = value;
+}
+
+static inline void
+avro_refcount_inc(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		__asm__ __volatile__ ("lock ; inc"REFCOUNT_SS" %0"
+				      :"=m" (refcount)
+				      :"m" (refcount));
+	}
+}
+
+static inline int
+avro_refcount_dec(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		char result;
+		__asm__ __volatile__ ("lock ; dec"REFCOUNT_SS" %0; setz %1"
+				      :"=m" (refcount), "=q" (result)
+				      :"m" (refcount));
+		return result;
+	}
+	return 0;
+}
+
+#undef REFCOUNT_SS
+
+
+/*-----------------------------------------------------------------------
+ * Raw PPC assembly
+ */
+
+#elif defined(__GNUC__) && defined(__ppc__)
+
+static inline int
+avro_refcount_LL_int(volatile int *ptr)
+{
+	int val;
+	__asm__ __volatile__ ("lwarx %[val],0,%[ptr]"
+			      : [val] "=r" (val)
+			      : [ptr] "r" (&ptr)
+			      : "cc");
+
+	return val;
+}
+
+/* Returns non-zero if the store was successful, zero otherwise. */
+static inline int
+avro_refcount_SC_int(volatile int *ptr, int val)
+{
+	int ret = 1; /* init to non-zero, will be reset to 0 if SC was successful */
+	__asm__ __volatile__ ("stwcx. %[val],0,%[ptr];\n"
+			      "beq 1f;\n"
+			      "li %[ret], 0;\n"
+			      "1: ;\n"
+			      : [ret] "=r" (ret)
+			      : [ptr] "r" (&ptr), [val] "r" (val), "0" (ret)
+			      : "cc", "memory");
+	return ret;
+}
+
+static inline void
+avro_refcount_set(volatile int *refcount, int value)
+{
+	*refcount = value;
+}
+
+static inline void
+avro_refcount_inc(volatile int *refcount)
+{
+	int prev;
+	do {
+		prev = avro_refcount_LL_int(refcount);
+		if (prev == (int) -1) {
+			return;
+		}
+	} while (!avro_refcount_SC_int(refcount, prev + 1));
+}
+
+static inline int
+avro_refcount_dec(volatile int *refcount)
+{
+	int prev;
+	do {
+		prev = avro_refcount_LL_int(refcount);
+		if (prev == (int) -1) {
+			return 0;
+		}
+	} while (!avro_refcount_SC_int(refcount, prev - 1));
+	return prev == 1;
+}
+
+
+/*-----------------------------------------------------------------------
+ * Windows intrinsics
+ */
+
+#elif defined(__WIN32__)
+
+#include <windows.h>
+#include <intrin.h>
+
+static inline void
+avro_refcount_set(volatile int *refcount, int value)
+{
+	*refcount = value;
+}
+
+static inline void
+avro_refcount_inc(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		_InterlockedIncrement(refcount);
+	}
+}
+
+static inline int
+avro_refcount_dec(volatile int *refcount)
+{
+	if (*refcount != (int) -1) {
+		return (_InterlockedDecrement(refcount) == 0);
+	}
+	return 0;
+}
+
+
+/*-----------------------------------------------------------------------
+ * Fallback
+ */
+
+#else
+#error "No atomic implementation!"
+#endif
+
+CLOSE_EXTERN
+#endif

Modified: avro/trunk/lang/c/src/datum.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum.c?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum.c (original)
+++ avro/trunk/lang/c/src/datum.c Tue Jul 12 20:21:04 2011
@@ -15,6 +15,7 @@
  * permissions and limitations under the License. 
  */
 
+#include "avro/refcount.h"
 #include "avro_errors.h"
 #include "avro_private.h"
 #include "allocation.h"
@@ -31,7 +32,7 @@ static void avro_datum_init(avro_datum_t
 {
 	datum->type = type;
 	datum->class_type = AVRO_DATUM;
-	datum->refcount = 1;
+	avro_refcount_set(&datum->refcount, 1);
 }
 
 static void
@@ -385,9 +386,9 @@ int avro_boolean_get(avro_datum_t datum,
 avro_datum_t avro_null(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_NULL,
-		.class_type = AVRO_DATUM,
-		.refcount = 1
+		AVRO_NULL,
+		AVRO_DATUM,
+		1
 	};
 	return avro_datum_incref(&obj);
 }
@@ -1097,16 +1098,15 @@ static void avro_datum_free(avro_datum_t
 
 avro_datum_t avro_datum_incref(avro_datum_t datum)
 {
-	if (datum && datum->refcount != (unsigned int)-1) {
-		++datum->refcount;
+	if (datum) {
+		avro_refcount_inc(&datum->refcount);
 	}
 	return datum;
 }
 
 void avro_datum_decref(avro_datum_t datum)
 {
-	if (datum && datum->refcount != (unsigned int)-1
-	    && --datum->refcount == 0) {
+	if (datum && avro_refcount_dec(&datum->refcount)) {
 		avro_datum_free(datum);
 	}
 }

Modified: avro/trunk/lang/c/src/io.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/io.c?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/src/io.c (original)
+++ avro/trunk/lang/c/src/io.c Tue Jul 12 20:21:04 2011
@@ -15,6 +15,7 @@
  * permissions and limitations under the License. 
  */
 
+#include "avro/refcount.h"
 #include "avro_errors.h"
 #include "avro_private.h"
 #include "allocation.h"
@@ -32,12 +33,12 @@ typedef enum avro_io_type_t avro_io_type
 
 struct avro_reader_t_ {
 	avro_io_type_t type;
-	unsigned long refcount;
+	volatile int  refcount;
 };
 
 struct avro_writer_t_ {
 	avro_io_type_t type;
-	unsigned long refcount;
+	volatile int  refcount;
 };
 
 struct _avro_reader_file_t {
@@ -79,13 +80,13 @@ struct _avro_writer_memory_t {
 static void reader_init(avro_reader_t reader, avro_io_type_t type)
 {
 	reader->type = type;
-	reader->refcount = 1;
+	avro_refcount_set(&reader->refcount, 1);
 }
 
 static void writer_init(avro_writer_t writer, avro_io_type_t type)
 {
 	writer->type = type;
-	writer->refcount = 1;
+	avro_refcount_set(&writer->refcount, 1);
 }
 
 avro_reader_t avro_reader_file(FILE * fp)

Modified: avro/trunk/lang/c/src/schema.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/schema.c?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/src/schema.c (original)
+++ avro/trunk/lang/c/src/schema.c Tue Jul 12 20:21:04 2011
@@ -15,6 +15,7 @@
  * permissions and limitations under the License. 
  */
 
+#include "avro/refcount.h"
 #include "avro_errors.h"
 #include "avro_private.h"
 #include "allocation.h"
@@ -39,7 +40,7 @@ static void avro_schema_init(avro_schema
 {
 	schema->type = type;
 	schema->class_type = AVRO_SCHEMA;
-	schema->refcount = 1;
+	avro_refcount_set(&schema->refcount, 1);
 }
 
 static int is_avro_id(const char *name)
@@ -183,16 +184,15 @@ static void avro_schema_free(avro_schema
 
 avro_schema_t avro_schema_incref(avro_schema_t schema)
 {
-	if (schema && schema->refcount != (unsigned int)-1) {
-		++schema->refcount;
+	if (schema) {
+		avro_refcount_inc(&schema->refcount);
 	}
 	return schema;
 }
 
 void avro_schema_decref(avro_schema_t schema)
 {
-	if (schema && schema->refcount != (unsigned int)-1
-	    && --schema->refcount == 0) {
+	if (schema && avro_refcount_dec(&schema->refcount)) {
 		avro_schema_free(schema);
 	}
 }
@@ -200,9 +200,9 @@ void avro_schema_decref(avro_schema_t sc
 avro_schema_t avro_schema_string(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_STRING,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_STRING,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -210,9 +210,9 @@ avro_schema_t avro_schema_string(void)
 avro_schema_t avro_schema_bytes(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_BYTES,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_BYTES,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -220,9 +220,9 @@ avro_schema_t avro_schema_bytes(void)
 avro_schema_t avro_schema_int(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_INT32,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_INT32,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -230,9 +230,9 @@ avro_schema_t avro_schema_int(void)
 avro_schema_t avro_schema_long(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_INT64,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_INT64,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -240,9 +240,9 @@ avro_schema_t avro_schema_long(void)
 avro_schema_t avro_schema_float(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_FLOAT,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_FLOAT,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -250,9 +250,9 @@ avro_schema_t avro_schema_float(void)
 avro_schema_t avro_schema_double(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_DOUBLE,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_DOUBLE,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -260,9 +260,9 @@ avro_schema_t avro_schema_double(void)
 avro_schema_t avro_schema_boolean(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_BOOLEAN,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_BOOLEAN,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }
@@ -270,9 +270,9 @@ avro_schema_t avro_schema_boolean(void)
 avro_schema_t avro_schema_null(void)
 {
 	static struct avro_obj_t obj = {
-		.type = AVRO_NULL,
-		.class_type = AVRO_SCHEMA,
-		.refcount = 1
+		AVRO_NULL,
+		AVRO_SCHEMA,
+		1
 	};
 	return avro_schema_incref(&obj);
 }

Added: avro/trunk/lang/c/tests/.gitignore
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/.gitignore?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/tests/.gitignore (added)
+++ avro/trunk/lang/c/tests/.gitignore Tue Jul 12 20:21:04 2011
@@ -0,0 +1,7 @@
+generate_interop_data
+performance
+test_avro_data
+test_avro_schema
+test_avro_schema_names
+test_cpp
+test_interop_data

Modified: avro/trunk/lang/c/tests/CMakeLists.txt
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/CMakeLists.txt?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/CMakeLists.txt (original)
+++ avro/trunk/lang/c/tests/CMakeLists.txt Tue Jul 12 20:21:04 2011
@@ -19,6 +19,10 @@
 
 add_executable(generate_interop_data generate_interop_data.c)
 target_link_libraries(generate_interop_data avro-static)
+
+add_executable(performance performance.c)
+target_link_libraries(performance avro-static)
+
 add_executable(test_interop_data test_interop_data.c)
 target_link_libraries(test_interop_data avro-static)
 

Modified: avro/trunk/lang/c/tests/Makefile.am
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/Makefile.am?rev=1145750&r1=1145749&r2=1145750&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/Makefile.am (original)
+++ avro/trunk/lang/c/tests/Makefile.am Tue Jul 12 20:21:04 2011
@@ -7,7 +7,7 @@ EXTRA_DIST=schema_tests test_valgrind
 
 check_PROGRAMS=test_avro_schema test_avro_schema_names test_avro_data test_cpp
 
-noinst_PROGRAMS=generate_interop_data test_interop_data
+noinst_PROGRAMS=generate_interop_data test_interop_data performance
 
 test_LDADD=$(top_builddir)/src/libavro.la
 
@@ -26,6 +26,9 @@ test_cpp_LDADD=$(test_LDADD)
 generate_interop_data_SOURCES=generate_interop_data.c
 generate_interop_data_LDADD=$(test_LDADD)
 
+performance_SOURCES=performance.c
+performance_LDADD=$(test_LDADD)
+
 test_interop_data_SOURCES=test_interop_data.c
 test_interop_data_LDADD=$(test_LDADD)
 

Added: avro/trunk/lang/c/tests/performance.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/performance.c?rev=1145750&view=auto
==============================================================================
--- avro/trunk/lang/c/tests/performance.c (added)
+++ avro/trunk/lang/c/tests/performance.c Tue Jul 12 20:21:04 2011
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "avro.h"
+#include "avro_private.h"
+
+/*
+ * A series of performance tests.
+ */
+
+typedef void
+(*test_func_t)(void);
+
+
+void init_rand(void)
+{
+	srand(time(NULL));
+}
+
+double rand_number(double from, double to)
+{
+	double range = to - from;
+	return from + ((double)rand() / (RAND_MAX + 1.0)) * range;
+}
+
+int64_t rand_int64(void)
+{
+	return (int64_t) rand_number(LONG_MIN, LONG_MAX);
+}
+
+int32_t rand_int32(void)
+{
+	return (int32_t) rand_number(INT_MIN, INT_MAX);
+}
+
+
+/**
+ * Tests the single-threaded performance of our reference counting
+ * mechanism.  We create a single datum, and then reference and
+ * deference it many many times.
+ */
+
+static void
+test_refcount(void)
+{
+	const unsigned long  NUM_TESTS = 100000000;
+	unsigned long  i;
+
+	avro_datum_t  datum = avro_int32(42);
+	for (i = 0; i < NUM_TESTS; i++) {
+		avro_datum_incref(datum);
+		avro_datum_decref(datum);
+	}
+	avro_datum_decref(datum);
+}
+
+
+/**
+ * Tests the performance of serializing and deserializing a somewhat
+ * complex record type.
+ */
+
+static void
+test_nested_record(void)
+{
+	static const char  *schema_json =
+		"{"
+		"  \"type\": \"record\","
+		"  \"name\": \"test\","
+		"  \"fields\": ["
+		"    { \"name\": \"i\", \"type\": \"int\" },"
+		"    { \"name\": \"l\", \"type\": \"long\" },"
+		"    { \"name\": \"s\", \"type\": \"string\" },"
+		"    {"
+		"      \"name\": \"subrec\","
+		"      \"type\": {"
+		"        \"type\": \"record\","
+		"        \"name\": \"sub\","
+		"        \"fields\": ["
+		"          { \"name\": \"f\", \"type\": \"float\" },"
+		"          { \"name\": \"d\", \"type\": \"double\" }"
+		"        ]"
+		"      }"
+		"    }"
+		"  ]"
+		"}";
+
+	static const char *strings[] = {
+		"Four score and seven years ago",
+		"our father brought forth on this continent",
+		"a new nation", "conceived in Liberty",
+		"and dedicated to the proposition that all men are created equal."
+	};
+	static const unsigned int  NUM_STRINGS =
+	    sizeof(strings) / sizeof(strings[0]);
+
+	int  rc;
+	static char  buf[4096];
+	avro_reader_t  reader;
+	avro_writer_t  writer;
+
+	avro_schema_t  schema = NULL;
+	avro_schema_error_t  error = NULL;
+	avro_schema_from_json(schema_json, strlen(schema_json),
+			      &schema, &error);
+
+	const unsigned long  NUM_TESTS = 100000;
+	unsigned long  i;
+
+	avro_datum_t  in = avro_datum_from_schema(schema);
+
+	for (i = 0; i < NUM_TESTS; i++) {
+		avro_record_set_field_value(rc, in, int32, "i", rand_int32());
+		avro_record_set_field_value(rc, in, int64, "l", rand_int64());
+		avro_record_set_field_value(rc, in, givestring, "s",
+					    strings[i % NUM_STRINGS], NULL);
+
+		avro_datum_t  subrec = NULL;
+		avro_record_get(in, "subrec", &subrec);
+		avro_record_set_field_value(rc, in, float, "f", rand_number(-1e10, 1e10));
+		avro_record_set_field_value(rc, in, double, "d", rand_number(-1e10, 1e10));
+
+		writer = avro_writer_memory(buf, sizeof(buf));
+		avro_write_data(writer, schema, in);
+		avro_writer_free(writer);
+
+		avro_datum_t  out = NULL;
+
+		reader = avro_reader_memory(buf, sizeof(buf));
+		avro_read_data(reader, schema, schema, &out);
+		avro_reader_free(reader);
+
+		avro_datum_equal(in, out);
+		avro_datum_decref(out);
+	}
+
+	avro_datum_decref(in);
+}
+
+
+/**
+ * Test harness
+ */
+
+#define NUM_RUNS  3
+
+int
+main(int argc, char **argv)
+{
+	AVRO_UNUSED(argc);
+	AVRO_UNUSED(argv);
+
+	init_rand();
+
+	unsigned int  i;
+	struct avro_tests {
+		const char  *name;
+		test_func_t  func;
+	} tests[] = {
+		{ "refcount", test_refcount },
+		{ "nested record", test_nested_record }
+	};
+
+	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+		fprintf(stderr, "**** Running %s ****\n", tests[i].name);
+		unsigned int  run;
+
+		double  sum = 0.0;
+
+		for (run = 1; run <= NUM_RUNS; run++) {
+			fprintf(stderr, "  Run %u\n", run);
+
+			clock_t  before = clock();
+			tests[i].func();
+			clock_t  after = clock();
+			double  secs = ((double) after-before) / CLOCKS_PER_SEC;
+			sum += secs;
+		}
+
+		fprintf(stderr, "  Average time: %.03lf seconds\n", sum / NUM_RUNS);
+	}
+
+	return EXIT_SUCCESS;
+}



Mime
View raw message