summaryrefslogtreecommitdiffstats
path: root/yql/essentials/minikql/jsonpath/benchmark/main.cpp
blob: c1c1974d9c002f0696c62b51870259ef479758d6 (plain) (blame)
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());
    }
}