Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * test_json_parser_perf.c
4 : * Performance test program for both flavors of the JSON parser
5 : *
6 : * Copyright (c) 2024-2026, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_json_parser/test_json_parser_perf.c
10 : *
11 : * This program tests either the standard (recursive descent) JSON parser
12 : * or the incremental (table driven) parser, but without breaking the input
13 : * into chunks in the latter case. Thus it can be used to compare the pure
14 : * parsing speed of the two parsers. If the "-i" option is used, then the
15 : * table driven parser is used. Otherwise, the recursive descent parser is
16 : * used.
17 : *
18 : * The remaining arguments are the number of parsing iterations to be done
19 : * and the file containing the JSON input.
20 : *
21 : *-------------------------------------------------------------------------
22 : */
23 :
24 : #include "postgres_fe.h"
25 : #include "common/jsonapi.h"
26 : #include "common/logging.h"
27 : #include "lib/stringinfo.h"
28 : #include "mb/pg_wchar.h"
29 : #include <stdio.h>
30 : #include <string.h>
31 :
32 : #define BUFSIZE 6000
33 :
34 : int
35 0 : main(int argc, char **argv)
36 : {
37 0 : char buff[BUFSIZE];
38 0 : FILE *json_file;
39 0 : JsonParseErrorType result;
40 0 : JsonLexContext *lex;
41 0 : StringInfoData json;
42 0 : int n_read;
43 0 : int iter;
44 0 : int use_inc = 0;
45 :
46 0 : pg_logging_init(argv[0]);
47 :
48 0 : initStringInfo(&json);
49 :
50 0 : if (strcmp(argv[1], "-i") == 0)
51 : {
52 0 : use_inc = 1;
53 0 : argv++;
54 0 : }
55 :
56 0 : sscanf(argv[1], "%d", &iter);
57 :
58 0 : if ((json_file = fopen(argv[2], PG_BINARY_R)) == NULL)
59 0 : pg_fatal("Could not open input file '%s': %m", argv[2]);
60 :
61 0 : while ((n_read = fread(buff, 1, 6000, json_file)) > 0)
62 : {
63 0 : appendBinaryStringInfo(&json, buff, n_read);
64 : }
65 0 : fclose(json_file);
66 0 : for (int i = 0; i < iter; i++)
67 : {
68 0 : if (use_inc)
69 : {
70 0 : lex = makeJsonLexContextIncremental(NULL, PG_UTF8, false);
71 0 : result = pg_parse_json_incremental(lex, &nullSemAction,
72 0 : json.data, json.len,
73 : true);
74 0 : freeJsonLexContext(lex);
75 0 : }
76 : else
77 : {
78 0 : lex = makeJsonLexContextCstringLen(NULL, json.data, json.len,
79 : PG_UTF8, false);
80 0 : result = pg_parse_json(lex, &nullSemAction);
81 0 : freeJsonLexContext(lex);
82 : }
83 0 : if (result != JSON_SUCCESS)
84 0 : pg_fatal("unexpected result %d (expecting %d) on parse",
85 : result, JSON_SUCCESS);
86 0 : }
87 0 : exit(0);
88 : }
|