1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to you under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 */
17
18 #include <limits.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22
23 #include "avro.h"
24 #include "avro_private.h"
25
26
27 /* The following definitions can be used as bitflags. They can also be
28 * passed in as the resolution_mode flags to the helper functions.
29 */
30 #define USE_MATCHED_SCHEMAS (0x00)
31 #define USE_RESOLVED_READER (0x01)
32 #define USE_RESOLVED_WRITER (0x02)
33 #define USE_BOTH_RESOLVED (0x03)
34
35
36 /*
37 * A series of performance tests.
38 */
39
40 typedef void
41 (*test_func_t)(unsigned long);
42
43
init_rand(void)44 void init_rand(void)
45 {
46 srand(time(NULL));
47 }
48
rand_number(double from,double to)49 double rand_number(double from, double to)
50 {
51 double range = to - from;
52 return from + ((double)rand() / (RAND_MAX + 1.0)) * range;
53 }
54
rand_int64(void)55 int64_t rand_int64(void)
56 {
57 return (int64_t) rand_number(LONG_MIN, LONG_MAX);
58 }
59
rand_int32(void)60 int32_t rand_int32(void)
61 {
62 return (int32_t) rand_number(INT_MIN, INT_MAX);
63 }
64
65
66 /**
67 * Tests the single-threaded performance of our reference counting
68 * mechanism. We create a single datum, and then reference and
69 * deference it many many times.
70 */
71
72 static void
test_refcount(unsigned long num_tests)73 test_refcount(unsigned long num_tests)
74 {
75 unsigned long i;
76
77 avro_datum_t datum = avro_int32(42);
78 for (i = 0; i < num_tests; i++) {
79 avro_datum_incref(datum);
80 avro_datum_decref(datum);
81 }
82 avro_datum_decref(datum);
83 }
84
85
86 /**
87 * Tests the performance of serializing and deserializing a somewhat
88 * complex record type using the legacy datum API.
89 */
90
91 static void
test_nested_record_datum(unsigned long num_tests)92 test_nested_record_datum(unsigned long num_tests)
93 {
94 static const char *schema_json =
95 "{"
96 " \"type\": \"record\","
97 " \"name\": \"test\","
98 " \"fields\": ["
99 " { \"name\": \"i\", \"type\": \"int\" },"
100 " { \"name\": \"l\", \"type\": \"long\" },"
101 " { \"name\": \"s\", \"type\": \"string\" },"
102 " {"
103 " \"name\": \"subrec\","
104 " \"type\": {"
105 " \"type\": \"record\","
106 " \"name\": \"sub\","
107 " \"fields\": ["
108 " { \"name\": \"f\", \"type\": \"float\" },"
109 " { \"name\": \"d\", \"type\": \"double\" }"
110 " ]"
111 " }"
112 " }"
113 " ]"
114 "}";
115
116 static const char *strings[] = {
117 "Four score and seven years ago",
118 "our father brought forth on this continent",
119 "a new nation", "conceived in Liberty",
120 "and dedicated to the proposition that all men are created equal."
121 };
122 static const unsigned int NUM_STRINGS =
123 sizeof(strings) / sizeof(strings[0]);
124
125 int rc;
126 static char buf[4096];
127 avro_reader_t reader = avro_reader_memory(buf, sizeof(buf));
128 avro_writer_t writer = avro_writer_memory(buf, sizeof(buf));
129
130 avro_schema_t schema = NULL;
131 avro_schema_error_t error = NULL;
132 avro_schema_from_json(schema_json, strlen(schema_json),
133 &schema, &error);
134
135 unsigned long i;
136
137 avro_datum_t in = avro_datum_from_schema(schema);
138
139 for (i = 0; i < num_tests; i++) {
140 avro_record_set_field_value(rc, in, int32, "i", rand_int32());
141 avro_record_set_field_value(rc, in, int64, "l", rand_int64());
142 avro_record_set_field_value(rc, in, givestring, "s",
143 strings[i % NUM_STRINGS], NULL);
144
145 avro_datum_t subrec = NULL;
146 avro_record_get(in, "subrec", &subrec);
147 avro_record_set_field_value(rc, in, float, "f", rand_number(-1e10, 1e10));
148 avro_record_set_field_value(rc, in, double, "d", rand_number(-1e10, 1e10));
149
150 avro_writer_reset(writer);
151 avro_write_data(writer, schema, in);
152
153 avro_datum_t out = NULL;
154
155 avro_reader_reset(reader);
156 avro_read_data(reader, schema, schema, &out);
157
158 avro_datum_equal(in, out);
159 avro_datum_decref(out);
160 }
161
162 avro_datum_decref(in);
163 avro_schema_decref(schema);
164 avro_writer_free(writer);
165 avro_reader_free(reader);
166 }
167
168
169 /**
170 * Tests the performance of serializing and deserializing a somewhat
171 * complex record type using the new value API, retrieving record fields
172 * by index.
173 */
174
175 static void
test_nested_record_value_by_index(unsigned long num_tests)176 test_nested_record_value_by_index(unsigned long num_tests)
177 {
178 static const char *schema_json =
179 "{"
180 " \"type\": \"record\","
181 " \"name\": \"test\","
182 " \"fields\": ["
183 " { \"name\": \"i\", \"type\": \"int\" },"
184 " { \"name\": \"l\", \"type\": \"long\" },"
185 " { \"name\": \"s\", \"type\": \"string\" },"
186 " {"
187 " \"name\": \"subrec\","
188 " \"type\": {"
189 " \"type\": \"record\","
190 " \"name\": \"sub\","
191 " \"fields\": ["
192 " { \"name\": \"f\", \"type\": \"float\" },"
193 " { \"name\": \"d\", \"type\": \"double\" }"
194 " ]"
195 " }"
196 " }"
197 " ]"
198 "}";
199
200 static char *strings[] = {
201 "Four score and seven years ago",
202 "our father brought forth on this continent",
203 "a new nation", "conceived in Liberty",
204 "and dedicated to the proposition that all men are created equal."
205 };
206 static const unsigned int NUM_STRINGS =
207 sizeof(strings) / sizeof(strings[0]);
208
209 static char buf[4096];
210 avro_reader_t reader = avro_reader_memory(buf, sizeof(buf));
211 avro_writer_t writer = avro_writer_memory(buf, sizeof(buf));
212
213 avro_schema_t schema = NULL;
214 avro_schema_error_t error = NULL;
215 avro_schema_from_json(schema_json, strlen(schema_json),
216 &schema, &error);
217
218 unsigned long i;
219
220 avro_value_iface_t *iface = avro_generic_class_from_schema(schema);
221
222 avro_value_t val;
223 avro_generic_value_new(iface, &val);
224
225 avro_value_t out;
226 avro_generic_value_new(iface, &out);
227
228 for (i = 0; i < num_tests; i++) {
229 avro_value_t field;
230
231 avro_value_get_by_index(&val, 0, &field, NULL);
232 avro_value_set_int(&field, rand_int32());
233
234 avro_value_get_by_index(&val, 1, &field, NULL);
235 avro_value_set_long(&field, rand_int64());
236
237 avro_wrapped_buffer_t wbuf;
238 avro_wrapped_buffer_new_string(&wbuf, strings[i % NUM_STRINGS]);
239 avro_value_get_by_index(&val, 2, &field, NULL);
240 avro_value_give_string_len(&field, &wbuf);
241
242 avro_value_t subrec;
243 avro_value_get_by_index(&val, 3, &subrec, NULL);
244
245 avro_value_get_by_index(&subrec, 0, &field, NULL);
246 avro_value_set_float(&field, rand_number(-1e10, 1e10));
247
248 avro_value_get_by_index(&subrec, 1, &field, NULL);
249 avro_value_set_double(&field, rand_number(-1e10, 1e10));
250
251 avro_writer_reset(writer);
252 avro_value_write(writer, &val);
253
254 avro_reader_reset(reader);
255 avro_value_read(reader, &out);
256
257 if (! avro_value_equal_fast(&val, &out) ) {
258 printf("Broken\n");
259 exit (1);
260 }
261 }
262
263 avro_value_decref(&val);
264 avro_value_decref(&out);
265 avro_value_iface_decref(iface);
266 avro_schema_decref(schema);
267 avro_writer_free(writer);
268 avro_reader_free(reader);
269 }
270
271
272
273 /**
274 * Tests the performance of serializing and deserializing a somewhat
275 * complex record type using the new value API, retrieving record fields
276 * by name.
277 */
278
279 static void
test_nested_record_value_by_name(unsigned long num_tests)280 test_nested_record_value_by_name(unsigned long num_tests)
281 {
282 static const char *schema_json =
283 "{"
284 " \"type\": \"record\","
285 " \"name\": \"test\","
286 " \"fields\": ["
287 " { \"name\": \"i\", \"type\": \"int\" },"
288 " { \"name\": \"l\", \"type\": \"long\" },"
289 " { \"name\": \"s\", \"type\": \"string\" },"
290 " {"
291 " \"name\": \"subrec\","
292 " \"type\": {"
293 " \"type\": \"record\","
294 " \"name\": \"sub\","
295 " \"fields\": ["
296 " { \"name\": \"f\", \"type\": \"float\" },"
297 " { \"name\": \"d\", \"type\": \"double\" }"
298 " ]"
299 " }"
300 " }"
301 " ]"
302 "}";
303
304 static char *strings[] = {
305 "Four score and seven years ago",
306 "our father brought forth on this continent",
307 "a new nation", "conceived in Liberty",
308 "and dedicated to the proposition that all men are created equal."
309 };
310 static const unsigned int NUM_STRINGS =
311 sizeof(strings) / sizeof(strings[0]);
312
313 static char buf[4096];
314 avro_reader_t reader = avro_reader_memory(buf, sizeof(buf));
315 avro_writer_t writer = avro_writer_memory(buf, sizeof(buf));
316
317 avro_schema_t schema = NULL;
318 avro_schema_error_t error = NULL;
319 avro_schema_from_json(schema_json, strlen(schema_json),
320 &schema, &error);
321
322 unsigned long i;
323
324 avro_value_iface_t *iface = avro_generic_class_from_schema(schema);
325
326 avro_value_t val;
327 avro_generic_value_new(iface, &val);
328
329 avro_value_t out;
330 avro_generic_value_new(iface, &out);
331
332 for (i = 0; i < num_tests; i++) {
333 avro_value_t field;
334
335 avro_value_get_by_name(&val, "i", &field, NULL);
336 avro_value_set_int(&field, rand_int32());
337
338 avro_value_get_by_name(&val, "l", &field, NULL);
339 avro_value_set_long(&field, rand_int64());
340
341 avro_wrapped_buffer_t wbuf;
342 avro_wrapped_buffer_new_string(&wbuf, strings[i % NUM_STRINGS]);
343 avro_value_get_by_name(&val, "s", &field, NULL);
344 avro_value_give_string_len(&field, &wbuf);
345
346 avro_value_t subrec;
347 avro_value_get_by_name(&val, "subrec", &subrec, NULL);
348
349 avro_value_get_by_name(&subrec, "f", &field, NULL);
350 avro_value_set_float(&field, rand_number(-1e10, 1e10));
351
352 avro_value_get_by_name(&subrec, "d", &field, NULL);
353 avro_value_set_double(&field, rand_number(-1e10, 1e10));
354
355 avro_writer_reset(writer);
356 avro_value_write(writer, &val);
357
358 avro_reader_reset(reader);
359 avro_value_read(reader, &out);
360
361 if (! avro_value_equal_fast(&val, &out) ) {
362 printf("Broken\n");
363 exit (1);
364 }
365 }
366
367 avro_value_decref(&val);
368 avro_value_decref(&out);
369 avro_value_iface_decref(iface);
370 avro_schema_decref(schema);
371 avro_writer_free(writer);
372 avro_reader_free(reader);
373 }
374
375
376
377 /**
378 * Helper function to test the performance of serializing and
379 * deserializing a given avro value using the provided function to
380 * populate avro value using the new value API. Allows testing using
381 * matching schemas or using schema resolution.
382 */
383
384 static void
test_generic_helper(unsigned long num_tests,int resolution_type,const char * schema_json,void (* populate_value_func)(avro_value_t *,unsigned long))385 test_generic_helper( unsigned long num_tests,
386 int resolution_type,
387 const char *schema_json,
388 void (*populate_value_func)(avro_value_t *,
389 unsigned long)
390 )
391 {
392 static char buf[4096];
393
394 avro_reader_t reader = avro_reader_memory(buf, sizeof(buf));
395 avro_writer_t writer = avro_writer_memory(buf, sizeof(buf));
396
397 avro_schema_t schema = NULL;
398 avro_schema_error_t error = NULL;
399 avro_schema_from_json(schema_json, strlen(schema_json),
400 &schema, &error);
401
402 unsigned long i;
403
404 avro_value_iface_t *writer_iface = avro_generic_class_from_schema(schema);
405 avro_value_iface_t *reader_iface = avro_generic_class_from_schema(schema);
406
407 avro_value_t val;
408 avro_generic_value_new(writer_iface, &val);
409
410 avro_value_t out;
411 avro_generic_value_new(reader_iface, &out);
412
413 /* Use resolved reader to resolve schemas while writing data to memory */
414 avro_value_iface_t *resolved_reader_iface = NULL;
415 avro_value_t resolved_reader_value;
416 if ( resolution_type & USE_RESOLVED_READER ) {
417 resolved_reader_iface = avro_resolved_reader_new( schema, schema );
418 avro_resolved_reader_new_value( resolved_reader_iface,
419 &resolved_reader_value );
420 avro_resolved_reader_set_source( &resolved_reader_value, &val );
421 }
422
423 /* Use resolved writer to resolve schemas while reading data from memory */
424 avro_value_iface_t *resolved_writer_iface = NULL;
425 avro_value_t resolved_writer_value;
426 if ( resolution_type & USE_RESOLVED_WRITER ) {
427 resolved_writer_iface = avro_resolved_writer_new( schema, schema );
428 avro_resolved_writer_new_value( resolved_writer_iface,
429 &resolved_writer_value );
430 avro_resolved_writer_set_dest( &resolved_writer_value, &out );
431 }
432
433 /* Set up pointers */
434 avro_value_t *p_value_to_write_to_memory = NULL;
435 avro_value_t *p_value_to_read_from_memory = NULL;
436
437 if ( resolution_type == USE_MATCHED_SCHEMAS ) {
438 p_value_to_write_to_memory = &val;
439 p_value_to_read_from_memory = &out;
440 }
441 else if ( resolution_type == USE_RESOLVED_READER ) {
442 p_value_to_write_to_memory = &resolved_reader_value;
443 p_value_to_read_from_memory = &out;
444 }
445 else if ( resolution_type == USE_RESOLVED_WRITER ) {
446 p_value_to_write_to_memory = &val;
447 p_value_to_read_from_memory = &resolved_writer_value;
448 }
449 else if ( resolution_type == USE_BOTH_RESOLVED ) {
450 p_value_to_write_to_memory = &resolved_reader_value;
451 p_value_to_read_from_memory = &resolved_writer_value;
452 }
453
454 /* Perform the tests */
455 for (i = 0; i < num_tests; i++) {
456
457 avro_value_reset(&val);
458
459 /* Execute the function to populate the Avro Value */
460 (*populate_value_func)(&val, i);
461
462 avro_writer_reset(writer);
463 avro_value_write(writer, p_value_to_write_to_memory);
464
465 avro_reader_reset(reader);
466 avro_value_read(reader, p_value_to_read_from_memory);
467
468 if (! avro_value_equal_fast(&val, &out) ) {
469 printf("Broken\n");
470 exit (1);
471 }
472 }
473
474 avro_value_decref(&val);
475 avro_value_decref(&out);
476 if ( resolution_type & USE_RESOLVED_READER ) {
477 avro_value_decref(&resolved_reader_value);
478 avro_value_iface_decref(resolved_reader_iface);
479 }
480 if ( resolution_type & USE_RESOLVED_WRITER ) {
481 avro_value_decref(&resolved_writer_value);
482 avro_value_iface_decref(resolved_writer_iface);
483 }
484 avro_value_iface_decref(writer_iface);
485 avro_value_iface_decref(reader_iface);
486 avro_schema_decref(schema);
487 avro_writer_free(writer);
488 avro_reader_free(reader);
489 }
490
491
492
493
494 /**
495 * Helper function to populate a somewhat complex record type using
496 * the new value API, retrieving record fields by index.
497 */
498
499 static const char *complex_record_schema_json =
500 "{"
501 " \"type\": \"record\","
502 " \"name\": \"test\","
503 " \"fields\": ["
504 " { \"name\": \"i\", \"type\": \"int\" },"
505 " { \"name\": \"l\", \"type\": \"long\" },"
506 " { \"name\": \"s\", \"type\": \"string\" },"
507 " {"
508 " \"name\": \"subrec\","
509 " \"type\": {"
510 " \"type\": \"record\","
511 " \"name\": \"sub\","
512 " \"fields\": ["
513 " { \"name\": \"f\", \"type\": \"float\" },"
514 " { \"name\": \"d\", \"type\": \"double\" }"
515 " ]"
516 " }"
517 " }"
518 " ]"
519 "}";
520
521
522
523 static void
populate_complex_record(avro_value_t * p_val,unsigned long i)524 populate_complex_record(avro_value_t *p_val, unsigned long i)
525 {
526 static char *strings[] = {
527 "Four score and seven years ago",
528 "our father brought forth on this continent",
529 "a new nation", "conceived in Liberty",
530 "and dedicated to the proposition that all men are created equal."
531 };
532 static const unsigned int NUM_STRINGS =
533 sizeof(strings) / sizeof(strings[0]);
534
535 avro_value_t field;
536
537 avro_value_get_by_index(p_val, 0, &field, NULL);
538 avro_value_set_int(&field, rand_int32());
539
540 avro_value_get_by_index(p_val, 1, &field, NULL);
541 avro_value_set_long(&field, rand_int64());
542
543 avro_wrapped_buffer_t wbuf;
544 avro_wrapped_buffer_new_string(&wbuf, strings[i % NUM_STRINGS]);
545 avro_value_get_by_index(p_val, 2, &field, NULL);
546 avro_value_give_string_len(&field, &wbuf);
547
548 avro_value_t subrec;
549 avro_value_get_by_index(p_val, 3, &subrec, NULL);
550
551 avro_value_get_by_index(&subrec, 0, &field, NULL);
552 avro_value_set_float(&field, rand_number(-1e10, 1e10));
553
554 avro_value_get_by_index(&subrec, 1, &field, NULL);
555 avro_value_set_double(&field, rand_number(-1e10, 1e10));
556
557 }
558
559
560
561 /**
562 * Tests the performance of serializing and deserializing a somewhat
563 * complex record type using the new value API, retrieving record
564 * fields by index. The functionality is almost identical to
565 * test_nested_record_value_by_index(), however, there may be some
566 * overhead of using function calls instead of inline code, and
567 * running some additional "if" statements..
568 */
569
570 static void
test_nested_record_value_by_index_matched_schemas(unsigned long num_tests)571 test_nested_record_value_by_index_matched_schemas(unsigned long num_tests)
572 {
573 test_generic_helper(num_tests,
574 USE_MATCHED_SCHEMAS,
575 complex_record_schema_json,
576 populate_complex_record);
577 }
578
579
580 /**
581 * Tests the performance of serializing and deserializing a somewhat
582 * complex record type using the new value API, retrieving record
583 * fields by index. Uses a resolved_writer to resolve between two
584 * (identical) schemas when reading the array.
585 */
586
587 static void
test_nested_record_value_by_index_resolved_writer(unsigned long num_tests)588 test_nested_record_value_by_index_resolved_writer(unsigned long num_tests)
589 {
590 test_generic_helper(num_tests,
591 USE_RESOLVED_WRITER,
592 complex_record_schema_json,
593 populate_complex_record);
594 }
595
596
597
598 /**
599 * Tests the performance of serializing and deserializing a somewhat
600 * complex record type using the new value API, retrieving record
601 * fields by index. Uses a resolved_reader to resolve between two
602 * (identical) schemas when writing the array.
603 */
604
605 static void
test_nested_record_value_by_index_resolved_reader(unsigned long num_tests)606 test_nested_record_value_by_index_resolved_reader(unsigned long num_tests)
607 {
608 test_generic_helper(num_tests,
609 USE_RESOLVED_READER,
610 complex_record_schema_json,
611 populate_complex_record);
612 }
613
614
615
616 /**
617 * Helper function to test the performance of serializing and
618 * deserializing a simple array using the new value API. Allows
619 * testing using matching schemas or using schema resolution.
620 */
621
622 static const char *simple_array_schema_json =
623 "{\"name\": \"a\", \"type\": \"array\", \"items\":\"long\"}";
624
625 static void
populate_simple_array(avro_value_t * p_val,unsigned long i)626 populate_simple_array(avro_value_t *p_val, unsigned long i)
627 {
628 const size_t array_length = 21;
629 avro_value_t field;
630 size_t idx;
631 size_t dummy_index;
632 (void) i;
633
634 for ( idx = 0; idx < array_length; idx++ ) {
635 avro_value_append(p_val, &field, &dummy_index);
636 avro_value_set_long(&field, rand_int64());
637 }
638 }
639
640
641
642 /**
643 * Tests the performance of serializing and deserializing a simple
644 * array using the new value API.
645 */
646
647 static void
test_simple_array(unsigned long num_tests)648 test_simple_array(unsigned long num_tests)
649 {
650 test_generic_helper(num_tests,
651 USE_MATCHED_SCHEMAS,
652 simple_array_schema_json,
653 populate_simple_array);
654 }
655
656
657
658 /**
659 * Tests the performance of serializing and deserializing a simple
660 * array using the new value API, using a resolved writer to resolve
661 * between (identical) reader and writer schemas, when reading the
662 * array.
663 */
664 static void
test_simple_array_resolved_writer(unsigned long num_tests)665 test_simple_array_resolved_writer(unsigned long num_tests)
666 {
667 test_generic_helper(num_tests,
668 USE_RESOLVED_WRITER,
669 simple_array_schema_json,
670 populate_simple_array);
671 }
672
673
674
675 /**
676 * Tests the performance of serializing and deserializing a simple
677 * array using the new value API, using a resolved reader to resolve
678 * between (identical) reader and writer schemas, when writing the
679 * array.
680 */
681
682 static void
test_simple_array_resolved_reader(unsigned long num_tests)683 test_simple_array_resolved_reader(unsigned long num_tests)
684 {
685 test_generic_helper(num_tests,
686 USE_RESOLVED_READER,
687 simple_array_schema_json,
688 populate_simple_array);
689 }
690
691
692
693
694 /**
695 * Helper function to test the performance of serializing and
696 * deserializing a nested array using the new value API. Allows
697 * testing using matching schemas or using schema resolution.
698 */
699
700 static const char *nested_array_schema_json =
701 "{\"type\":\"array\", \"items\": {\"type\": \"array\", \"items\": \"long\"}}";
702
703
704 static void
populate_nested_array(avro_value_t * p_val,unsigned long i)705 populate_nested_array(avro_value_t *p_val, unsigned long i)
706 {
707
708 const size_t array_length = 7;
709 const size_t subarray_length = 3;
710 avro_value_t subarray;
711 avro_value_t field;
712 size_t idx;
713 size_t jdx;
714 size_t dummy_index;
715 (void) i;
716
717 for ( idx = 0; idx < array_length; idx++ ) {
718 avro_value_append(p_val, &subarray, &dummy_index);
719 for ( jdx = 0; jdx < subarray_length; jdx ++ ) {
720 avro_value_append(&subarray, &field, &dummy_index);
721 avro_value_set_long(&field, rand_int64());
722 }
723 }
724 }
725
726
727 /**
728 * Tests the performance of serializing and deserializing a nested
729 * array using the new value API.
730 */
731
732 static void
test_nested_array(unsigned long num_tests)733 test_nested_array(unsigned long num_tests)
734 {
735 test_generic_helper(num_tests,
736 USE_MATCHED_SCHEMAS,
737 nested_array_schema_json,
738 populate_nested_array);
739 }
740
741
742 /**
743 * Tests the performance of serializing and deserializing a nested
744 * array using the new value API, using a resolved writer to resolve
745 * between (identical) reader and writer schemas, when reading the
746 * array.
747 */
748
749 static void
test_nested_array_resolved_writer(unsigned long num_tests)750 test_nested_array_resolved_writer(unsigned long num_tests)
751 {
752 test_generic_helper(num_tests,
753 USE_RESOLVED_WRITER,
754 nested_array_schema_json,
755 populate_nested_array);
756 }
757
758
759 /**
760 * Tests the performance of serializing and deserializing a nested
761 * array using the new value API, using a resolved reader to resolve
762 * between (identical) reader and writer schemas, when writing the
763 * array.
764 */
765
766 static void
test_nested_array_resolved_reader(unsigned long num_tests)767 test_nested_array_resolved_reader(unsigned long num_tests)
768 {
769 test_generic_helper(num_tests,
770 USE_RESOLVED_READER,
771 nested_array_schema_json,
772 populate_nested_array);
773 }
774
775
776
777 /**
778 * Test harness
779 */
780
781 #define NUM_RUNS 3
782
783 int
main(int argc,char ** argv)784 main(int argc, char **argv)
785 {
786 AVRO_UNUSED(argc);
787 AVRO_UNUSED(argv);
788
789 init_rand();
790
791 unsigned int i;
792 struct avro_tests {
793 const char *name;
794 unsigned long num_tests;
795 test_func_t func;
796 } tests[] = {
797 { "refcount", 100000000,
798 test_refcount },
799 { "nested record (legacy)", 100000,
800 test_nested_record_datum },
801 { "nested record (value by index)", 1000000,
802 test_nested_record_value_by_index },
803 { "nested record (value by name)", 1000000,
804 test_nested_record_value_by_name },
805 { "nested record (value by index) matched schemas", 1000000,
806 test_nested_record_value_by_index_matched_schemas },
807 { "nested record (value by index) resolved writer", 1000000,
808 test_nested_record_value_by_index_resolved_writer },
809 { "nested record (value by index) resolved reader", 1000000,
810 test_nested_record_value_by_index_resolved_reader },
811 { "simple array matched schemas", 250000,
812 test_simple_array },
813 { "simple array resolved writer", 250000,
814 test_simple_array_resolved_writer },
815 { "simple array resolved reader", 250000,
816 test_simple_array_resolved_reader },
817 { "nested array matched schemas", 250000,
818 test_nested_array },
819 { "nested array resolved writer", 250000,
820 test_nested_array_resolved_writer },
821 { "nested array resolved reader", 250000,
822 test_nested_array_resolved_reader },
823 };
824
825 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
826 fprintf(stderr, "**** Running %s ****\n %lu tests per run\n",
827 tests[i].name, tests[i].num_tests);
828 unsigned int run;
829
830 double sum = 0.0;
831
832 for (run = 1; run <= NUM_RUNS; run++) {
833 fprintf(stderr, " Run %u\n", run);
834
835 clock_t before = clock();
836 tests[i].func(tests[i].num_tests);
837 clock_t after = clock();
838 double secs = ((double) after-before) / CLOCKS_PER_SEC;
839 sum += secs;
840 }
841
842 fprintf(stderr, " Average time: %.03lfs\n", sum / NUM_RUNS);
843 fprintf(stderr, " Tests/sec: %.0lf\n",
844 tests[i].num_tests / (sum / NUM_RUNS));
845 }
846
847 return EXIT_SUCCESS;
848 }
849