Skip to content

Commit

Permalink
Improve statement memory consumption using single NullNode instance.
Browse files Browse the repository at this point in the history
  • Loading branch information
asfernandes committed Jun 6, 2020
1 parent 030d963 commit 0da3d68
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 41 deletions.
37 changes: 14 additions & 23 deletions src/dsql/ExprNodes.cpp
Expand Up @@ -4882,7 +4882,7 @@ DmlNode* DefaultNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
}
}

return FB_NEW_POOL(pool) NullNode(pool);
return &NullNode::INSTANCE;
}
}

Expand Down Expand Up @@ -4914,7 +4914,7 @@ ValueExprNode* DefaultNode::createFromField(thread_db* tdbb, CompilerScratch* cs
return NodeCopier(csb->csb_pool, csb, map).copy(tdbb, fld->fld_default_value);
}
else
return FB_NEW_POOL(csb->csb_pool) NullNode(csb->csb_pool);
return &NullNode::INSTANCE;
}

string DefaultNode::internalPrint(NodePrinter& printer) const
Expand Down Expand Up @@ -5820,7 +5820,7 @@ DmlNode* FieldNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
else
{
if (relation->rel_flags & REL_system)
return FB_NEW_POOL(pool) NullNode(pool);
return &NullNode::INSTANCE;

if (tdbb->getAttachment()->isGbak())
{
Expand Down Expand Up @@ -5863,7 +5863,7 @@ DmlNode* FieldNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* cs
!(*temp_rel->rel_fields)[id])
{
if (temp_rel->rel_flags & REL_system)
return FB_NEW_POOL(pool) NullNode(pool);
return &NullNode::INSTANCE;
}
}
}
Expand Down Expand Up @@ -6057,7 +6057,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec

if ((context->ctx_flags & CTX_view_with_check_store) && !field)
{
node = FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
node = &NullNode::INSTANCE;
node->line = line;
node->column = column;
}
Expand Down Expand Up @@ -6088,7 +6088,7 @@ ValueExprNode* FieldNode::internalDsqlPass(DsqlCompilerScratch* dsqlScratch, Rec
doDsqlPass(dsqlScratch, dsqlIndices, false) : NULL;

if (context->ctx_flags & CTX_null)
node = FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
node = &NullNode::INSTANCE;
else if (field)
node = MAKE_field(context, field, indices);
else
Expand Down Expand Up @@ -8813,10 +8813,12 @@ ValueExprNode* NegateNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)

static RegisterNode<NullNode> regNullNode({blr_null});

GlobalPtr<NullNode> NullNode::INSTANCE;

DmlNode* NullNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerScratch* /*csb*/,
const UCHAR /*blrOp*/)
{
return FB_NEW_POOL(pool) NullNode(pool);
return &INSTANCE;
}

string NullNode::internalPrint(NodePrinter& printer) const
Expand Down Expand Up @@ -8863,18 +8865,7 @@ void NullNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* desc)

ValueExprNode* NullNode::copy(thread_db* tdbb, NodeCopier& /*copier*/) const
{
return FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
}

ValueExprNode* NullNode::pass2(thread_db* tdbb, CompilerScratch* csb)
{
ValueExprNode::pass2(tdbb, csb);

dsc desc;
getDesc(tdbb, csb, &desc);
impureOffset = CMP_impure(csb, sizeof(impure_value));

return this;
return &INSTANCE;
}

dsc* NullNode::execute(thread_db* /*tdbb*/, jrd_req* /*request*/) const
Expand Down Expand Up @@ -9790,7 +9781,7 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
raiseError(context);

if (context->ctx_flags & CTX_null)
return FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
return &NullNode::INSTANCE;

PASS1_ambiguity_check(dsqlScratch, getAlias(true), contexts);

Expand Down Expand Up @@ -9828,7 +9819,7 @@ ValueExprNode* RecordKeyNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
raiseError(context);

if (context->ctx_flags & CTX_null)
return FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
return &NullNode::INSTANCE;

RelationSourceNode* relNode = FB_NEW_POOL(dsqlScratch->getPool()) RelationSourceNode(
dsqlScratch->getPool());
Expand Down Expand Up @@ -10120,7 +10111,7 @@ ValueExprNode* RecordKeyNode::pass1(thread_db* tdbb, CompilerScratch* csb)
eqlNode->arg2 = literal;

// THEN: NULL
valueIfNode->trueValue = FB_NEW_POOL(csb->csb_pool) NullNode(csb->csb_pool);
valueIfNode->trueValue = &NullNode::INSTANCE;

// ELSE: RDB$DB_KEY
valueIfNode->falseValue = node;
Expand Down Expand Up @@ -10960,7 +10951,7 @@ ValueExprNode* SubQueryNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
RseNode* rse = PASS1_rse(dsqlScratch, nodeAs<SelectExprNode>(dsqlRse), false);

SubQueryNode* node = FB_NEW_POOL(dsqlScratch->getPool()) SubQueryNode(dsqlScratch->getPool(), blrOp, rse,
rse->dsqlSelectList->items[0], FB_NEW_POOL(dsqlScratch->getPool()) NullNode(dsqlScratch->getPool()));
rse->dsqlSelectList->items[0], &NullNode::INSTANCE);

// Finish off by cleaning up contexts.
dsqlScratch->context->clear(base);
Expand Down
10 changes: 8 additions & 2 deletions src/dsql/ExprNodes.h
Expand Up @@ -26,6 +26,7 @@
#include "firebird/impl/blr.h"
#include "../dsql/Nodes.h"
#include "../dsql/NodePrinter.h"
#include "../common/classes/init.h"
#include "../dsql/pass1_proto.h"

class SysFunction;
Expand Down Expand Up @@ -1169,12 +1170,15 @@ class NegateNode : public TypedNode<ValueExprNode, ExprNode::TYPE_NEGATE>

class NullNode : public TypedNode<ValueExprNode, ExprNode::TYPE_NULL>
{
public:
private:
friend class Firebird::GlobalPtr<NullNode>;

explicit NullNode(MemoryPool& pool)
: TypedNode<ValueExprNode, ExprNode::TYPE_NULL>(pool)
{
}

public:
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);

virtual Firebird::string internalPrint(NodePrinter& printer) const;
Expand All @@ -1184,8 +1188,10 @@ class NullNode : public TypedNode<ValueExprNode, ExprNode::TYPE_NULL>

virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual ValueExprNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual dsc* execute(thread_db* tdbb, jrd_req* request) const;

public:
static Firebird::GlobalPtr<NullNode> INSTANCE;

This comment has been minimized.

Copy link
@dyemanov

dyemanov Jun 7, 2020

Member

I would rather prefer to have it declared as private and define static NullNode::instance() to be used instead of &NullNode::INSTANCE.

};


Expand Down
2 changes: 1 addition & 1 deletion src/dsql/StmtNodes.cpp
Expand Up @@ -9122,7 +9122,7 @@ static StmtNode* dsqlNullifyReturning(DsqlCompilerScratch* dsqlScratch, StmtNode
++ret_ptr, ++null_ptr)
{
AssignmentNode* assign = FB_NEW_POOL(pool) AssignmentNode(pool);
assign->asgnFrom = FB_NEW_POOL(pool) NullNode(pool);
assign->asgnFrom = &NullNode::INSTANCE;
assign->asgnTo = nodeAs<AssignmentNode>(*ret_ptr)->asgnTo;
*null_ptr = assign;
}
Expand Down
26 changes: 13 additions & 13 deletions src/dsql/parse.y
Expand Up @@ -6723,14 +6723,14 @@ exec_function
: udf
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = newNode<NullNode>();
node->asgnTo = &NullNode::INSTANCE;
node->asgnFrom = $1;
$$ = node;
}
| non_aggregate_function
{
AssignmentNode* node = newNode<AssignmentNode>();
node->asgnTo = newNode<NullNode>();
node->asgnTo = &NullNode::INSTANCE;
node->asgnFrom = $1;
$$ = node;
}
Expand Down Expand Up @@ -7750,11 +7750,11 @@ aggregate_function
$$ = $1;

if ($$->aggInfo.blr == blr_agg_count2 && !$$->arg) // count(*)
$$->arg = newNode<ValueIfNode>($5, MAKE_const_slong(1), newNode<NullNode>());
$$->arg = newNode<ValueIfNode>($5, MAKE_const_slong(1), &NullNode::INSTANCE);
else
{
fb_assert($$->arg);
$$->arg = newNode<ValueIfNode>($5, $$->arg, newNode<NullNode>());
$$->arg = newNode<ValueIfNode>($5, $$->arg, &NullNode::INSTANCE);
}
}
;
Expand Down Expand Up @@ -7854,15 +7854,15 @@ window_function
| LAG '(' value ',' value ',' value ')'
{ $$ = newNode<LagWinNode>($3, $5, $7); }
| LAG '(' value ',' value ')'
{ $$ = newNode<LagWinNode>($3, $5, newNode<NullNode>()); }
{ $$ = newNode<LagWinNode>($3, $5, &NullNode::INSTANCE); }
| LAG '(' value ')'
{ $$ = newNode<LagWinNode>($3, MAKE_const_slong(1), newNode<NullNode>()); }
{ $$ = newNode<LagWinNode>($3, MAKE_const_slong(1), &NullNode::INSTANCE); }
| LEAD '(' value ',' value ',' value ')'
{ $$ = newNode<LeadWinNode>($3, $5, $7); }
| LEAD '(' value ',' value ')'
{ $$ = newNode<LeadWinNode>($3, $5, newNode<NullNode>()); }
{ $$ = newNode<LeadWinNode>($3, $5, &NullNode::INSTANCE); }
| LEAD '(' value ')'
{ $$ = newNode<LeadWinNode>($3, MAKE_const_slong(1), newNode<NullNode>()); }
{ $$ = newNode<LeadWinNode>($3, MAKE_const_slong(1), &NullNode::INSTANCE); }
| NTILE '(' ntile_arg ')'
{ $$ = newNode<NTileWinNode>($3); }
;
Expand Down Expand Up @@ -8367,7 +8367,7 @@ case_abbreviation
: NULLIF '(' value ',' value ')'
{
ComparativeBoolNode* condition = newNode<ComparativeBoolNode>(blr_eql, $3, $5);
$$ = newNode<ValueIfNode>(condition, newNode<NullNode>(), $3);
$$ = newNode<ValueIfNode>(condition, &NullNode::INSTANCE, $3);
}
| IIF '(' search_condition ',' value ',' value ')'
{ $$ = newNode<ValueIfNode>($3, $5, $7); }
Expand Down Expand Up @@ -8466,10 +8466,10 @@ searched_case
%type <valueIfNode> searched_when_clause
searched_when_clause
: WHEN search_condition THEN case_result
{ $$ = newNode<ValueIfNode>($2, $4, newNode<NullNode>()); }
{ $$ = newNode<ValueIfNode>($2, $4, &NullNode::INSTANCE); }
| searched_when_clause WHEN search_condition THEN case_result
{
ValueIfNode* cond = newNode<ValueIfNode>($3, $5, newNode<NullNode>());
ValueIfNode* cond = newNode<ValueIfNode>($3, $5, &NullNode::INSTANCE);
ValueIfNode* last = $1;
ValueIfNode* next;

Expand Down Expand Up @@ -8552,14 +8552,14 @@ distinct_noise
%type <valueExprNode> null_value
null_value
: NULL
{ $$ = newNode<NullNode>(); }
{ $$ = &NullNode::INSTANCE; }
| UNKNOWN
{
dsql_fld* field = newNode<dsql_fld>();
field->dtype = dtype_boolean;
field->length = sizeof(UCHAR);

CastNode* castNode = newNode<CastNode>(newNode<NullNode>(), field);
CastNode* castNode = newNode<CastNode>(&NullNode::INSTANCE, field);
castNode->dsqlAlias = "CONSTANT";
$$ = castNode;
}
Expand Down
2 changes: 1 addition & 1 deletion src/dsql/pass1.cpp
Expand Up @@ -1415,7 +1415,7 @@ void PASS1_expand_select_node(DsqlCompilerScratch* dsqlScratch, ExprNode* node,
if (!select_item)
{
if (context->ctx_flags & CTX_null)
select_item = FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
select_item = &NullNode::INSTANCE;
else
select_item = MAKE_field(context, field, NULL);
}
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/Optimizer.cpp
Expand Up @@ -1290,7 +1290,7 @@ InversionNode* OptimizerRetrieval::makeIndexScanNode(IndexScratch* indexScratch)
{
if (segment[i]->scanType == segmentScanMissing)
{
*lower++ = *upper++ = FB_NEW_POOL(*tdbb->getDefaultPool()) NullNode(*tdbb->getDefaultPool());
*lower++ = *upper++ = &NullNode::INSTANCE;
ignoreNullsOnScan = false;
}
else
Expand Down

0 comments on commit 0da3d68

Please sign in to comment.