Skip to content

Commit 94d2c3b

Browse files
authored
visit & hash evaluation key in the one pass (#8277)
1 parent da98ea2 commit 94d2c3b

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

ydb/library/yql/core/services/yql_eval_expr.cpp

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,51 @@ static THashSet<TStringBuf> SubqueryExpandFuncs = {
4545
TStringBuf("SubqueryAssumeOrderBy")
4646
};
4747

48-
TString MakeCacheKey(const TExprNode& root, TExprContext& ctx) {
49-
TConvertToAstSettings settings;
50-
settings.NormalizeAtomFlags = true;
51-
settings.AllowFreeArgs = false;
52-
settings.RefAtoms = true;
53-
settings.NoInlineFunc = [](const TExprNode&) { return true; };
54-
auto ast = ConvertToAst(root, ctx, settings);
55-
YQL_ENSURE(ast.Root);
56-
auto str = ast.Root->ToString();
57-
SHA256_CTX sha;
58-
SHA256_Init(&sha);
59-
SHA256_Update(&sha, str.Data(), str.Size());
60-
unsigned char hash[SHA256_DIGEST_LENGTH];
61-
SHA256_Final(hash, &sha);
62-
return TString((const char*)hash, sizeof(hash));
48+
class TCacheKeyBuilder {
49+
public:
50+
TString Process(const TExprNode& root) {
51+
SHA256_Init(&Sha);
52+
unsigned char hash[SHA256_DIGEST_LENGTH];
53+
Visit(root);
54+
SHA256_Final(hash, &Sha);
55+
return TString((const char*)hash, sizeof(hash));
56+
}
57+
58+
private:
59+
void Visit(const TExprNode& node) {
60+
auto [it, inserted] = Visited.emplace(&node, Visited.size());
61+
SHA256_Update(&Sha, &it->second, sizeof(it->second));
62+
if (!inserted) {
63+
return;
64+
}
65+
66+
ui32 type = node.Type();
67+
SHA256_Update(&Sha, &type, sizeof(type));
68+
if (node.Type() == TExprNode::EType::Atom || node.Type() == TExprNode::EType::Callable) {
69+
ui32 textLen = node.Content().size();
70+
SHA256_Update(&Sha, &textLen, sizeof(textLen));
71+
SHA256_Update(&Sha, node.Content().Data(), textLen);
72+
}
73+
74+
if (node.Type() == TExprNode::EType::Atom || node.Type() == TExprNode::EType::Argument || node.Type() == TExprNode::EType::World) {
75+
return;
76+
}
77+
78+
ui32 len = node.ChildrenSize();
79+
SHA256_Update(&Sha, &len, sizeof(len));
80+
for (const auto& child : node.Children()) {
81+
Visit(*child);
82+
}
83+
}
84+
85+
private:
86+
SHA256_CTX Sha;
87+
TNodeMap<ui64> Visited;
88+
};
89+
90+
TString MakeCacheKey(const TExprNode& root) {
91+
TCacheKeyBuilder builder;
92+
return builder.Process(root);
6393
}
6494

6595
bool CheckPendingArgs(const TExprNode& root, TNodeSet& visited, TNodeMap<const TExprNode*>& activeArgs, const TNodeMap<ui32>& externalWorlds, TExprContext& ctx,
@@ -1053,7 +1083,7 @@ IGraphTransformer::TStatus EvaluateExpression(const TExprNode::TPtr& input, TExp
10531083
TString yson;
10541084
TString key;
10551085
if (types.QContext) {
1056-
key = MakeCacheKey(*clonedArg, ctx);
1086+
key = MakeCacheKey(*clonedArg);
10571087
}
10581088

10591089
if (types.QContext.CanRead()) {

0 commit comments

Comments
 (0)