1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#include <yql/essentials/minikql/dom/json.h>
#include <yql/essentials/minikql/jsonpath/jsonpath.h>
#include <yql/essentials/minikql/computation/mkql_value_builder.h>
#include <yql/essentials/minikql/computation/mkql_computation_node_holders.h>
#include <yql/essentials/minikql/invoke_builtins/mkql_builtins.h>
#include <yql/essentials/minikql/mkql_mem_info.h>
#include <yql/essentials/minikql/mkql_function_registry.h>
#include <yql/essentials/minikql/mkql_alloc.h>
#include <yql/essentials/minikql/mkql_node.h>
#include <library/cpp/json/json_value.h>
#include <library/cpp/testing/benchmark/bench.h>
#include <util/random/fast.h>
using namespace NJson;
using namespace NYql;
using namespace NYql::NDom;
using namespace NYql::NUdf;
using namespace NYql::NJsonPath;
using namespace NJson;
using namespace NKikimr::NMiniKQL;
TString RandomString(ui32 min, ui32 max) {
static TReallyFastRng32 rand(0);
TString result;
const ui32 length = rand.Uniform(min, max + 1);
result.reserve(length);
for (ui32 i = 0; i < length; ++i) {
result.push_back(char(rand.Uniform('a', 'z' + 1)));
}
return result;
}
TString RandomString(ui32 length) {
return RandomString(length, length);
}
TString GenerateRandomJson() {
TJsonMap result;
TJsonMap id;
id.InsertValue("id", TJsonValue(RandomString(24)));
id.InsertValue("issueId", TJsonValue(RandomString(24)));
result.InsertValue("_id", std::move(id));
result.InsertValue("@class", TJsonValue(RandomString(60)));
result.InsertValue("author", TJsonValue(RandomString(10)));
result.InsertValue("transitionId", TJsonValue(RandomString(24)));
TJsonArray comments;
for (ui32 i = 0; i < 30; i++) {
TJsonMap comment;
comment.InsertValue("id", TJsonValue(RandomString(24)));
comment.InsertValue("newText", TJsonValue(RandomString(150)));
comments.AppendValue(std::move(comment));
}
TJsonMap changes;
changes.InsertValue("comment", std::move(comments));
result.InsertValue("changes", std::move(changes));
return result.GetStringRobust();
}
const size_t MAX_PARSE_ERRORS = 100;
#define PREPARE() \
TIntrusivePtr<IFunctionRegistry> FunctionRegistry(CreateFunctionRegistry(CreateBuiltinRegistry())); \
TScopedAlloc Alloc(__LOCATION__); \
TTypeEnvironment Env(Alloc); \
TMemoryUsageInfo MemInfo("Memory"); \
THolderFactory HolderFactory(Alloc.Ref(), MemInfo, FunctionRegistry.Get()); \
TDefaultValueBuilder ValueBuilder(HolderFactory);
Y_CPU_BENCHMARK(JsonPath, iface) {
PREPARE()
const TString json = GenerateRandomJson();
const TUnboxedValue dom = TryParseJsonDom(json, &ValueBuilder);
for (size_t i = 0; i < iface.Iterations(); i++) {
TIssues issues;
const auto jsonPath = ParseJsonPath("$.'_id'.issueId", issues, MAX_PARSE_ERRORS);
const auto result = ExecuteJsonPath(jsonPath, TValue(dom), TVariablesMap(), &ValueBuilder);
Y_ABORT_UNLESS(!result.IsError());
}
}
Y_CPU_BENCHMARK(JsonPathLikeRegexWithCompile, iface) {
PREPARE()
const TString json = GenerateRandomJson();
const TUnboxedValue dom = TryParseJsonDom(json, &ValueBuilder);
for (size_t i = 0; i < iface.Iterations(); i++) {
TIssues issues;
const auto jsonPath = ParseJsonPath("$[*] like_regex \"[0-9]+\"", issues, MAX_PARSE_ERRORS);
const auto result = ExecuteJsonPath(jsonPath, TValue(dom), TVariablesMap(), &ValueBuilder);
Y_ABORT_UNLESS(!result.IsError());
}
}
Y_CPU_BENCHMARK(JsonPathLikeRegex, iface) {
PREPARE()
const TString json = GenerateRandomJson();
const TUnboxedValue dom = TryParseJsonDom(json, &ValueBuilder);
TIssues issues;
const auto jsonPath = ParseJsonPath("$[*] like_regex \"[0-9]+\"", issues, MAX_PARSE_ERRORS);
for (size_t i = 0; i < iface.Iterations(); i++) {
const auto result = ExecuteJsonPath(jsonPath, TValue(dom), TVariablesMap(), &ValueBuilder);
Y_ABORT_UNLESS(!result.IsError());
}
}
|