From a7aa608e0f5910f9c73a530a66142c08e3d9043a Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 16 Nov 2018 10:25:34 -0800 Subject: [PATCH] Inline hot path of slot_getsomeattrs(). This yields a minor speedup, which roughly balances the loss from the upcoming introduction of callbacks to do some operations on slots. Author: Andres Freund Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de --- src/backend/executor/execExprInterp.c | 1 - src/backend/executor/execTuples.c | 32 ++++++++++++--------------- src/backend/jit/llvm/llvmjit.c | 4 ++-- src/backend/jit/llvm/llvmjit_expr.c | 2 +- src/backend/jit/llvm/llvmjit_types.c | 2 +- src/include/executor/tuptable.h | 13 ++++++++++- src/include/jit/llvmjit.h | 2 +- 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 9f61ef76c2..1f9f583cfb 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -428,7 +428,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) { CheckOpSlotCompatibility(op, innerslot); - /* XXX: worthwhile to check tts_nvalid inline first? */ slot_getsomeattrs(innerslot, op->d.fetch.last_var); EEO_NEXT(); diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 2cd7e5c866..4d92cf1269 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -1183,22 +1183,19 @@ slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull) } /* - * slot_getsomeattrs - * This function forces the entries of the slot's Datum/isnull - * arrays to be valid at least up through the attnum'th entry. + * slot_getsomeattrs_int - workhorse for slot_getsomeattrs() */ void -slot_getsomeattrs(TupleTableSlot *slot, int attnum) +slot_getsomeattrs_int(TupleTableSlot *slot, int attnum) { HeapTuple tuple; int attno; - /* Quick out if we have 'em all already */ - if (slot->tts_nvalid >= attnum) - return; + /* Check for caller errors */ + Assert(slot->tts_nvalid < attnum); /* slot_getsomeattr checked */ + Assert(attnum > 0); - /* Check for caller error */ - if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts) + if (unlikely(attnum > slot->tts_tupleDescriptor->natts)) elog(ERROR, "invalid attribute number %d", attnum); /* @@ -1209,9 +1206,7 @@ slot_getsomeattrs(TupleTableSlot *slot, int attnum) if (tuple == NULL) /* internal error */ elog(ERROR, "cannot extract attribute from empty tuple slot"); - /* - * load up any slots available from physical tuple - */ + /* Fetch as many attributes as possible from the underlying tuple. */ attno = HeapTupleHeaderGetNatts(tuple->t_data); attno = Min(attno, attnum); @@ -1220,13 +1215,14 @@ slot_getsomeattrs(TupleTableSlot *slot, int attnum) attno = slot->tts_nvalid; /* - * If tuple doesn't have all the atts indicated by attnum, read the rest - * as NULLs or missing values + * If the underlying tuple doesn't have enough attributes, tuple descriptor + * must have the missing attributes. */ - if (attno < attnum) - slot_getmissingattrs(slot, attno, attnum); - - slot->tts_nvalid = attnum; + if (unlikely(slot->tts_nvalid < attnum)) + { + slot_getmissingattrs(slot, slot->tts_nvalid, attnum); + slot->tts_nvalid = attnum; + } } /* ---------------------------------------------------------------- diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index 168072afd2..16519079e3 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -79,7 +79,7 @@ LLVMTypeRef StructAggStatePerTransData; LLVMValueRef AttributeTemplate; LLVMValueRef FuncStrlen; LLVMValueRef FuncVarsizeAny; -LLVMValueRef FuncSlotGetsomeattrs; +LLVMValueRef FuncSlotGetsomeattrsInt; LLVMValueRef FuncSlotGetmissingattrs; LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; LLVMValueRef FuncExecEvalArrayRefSubscript; @@ -820,7 +820,7 @@ llvm_create_types(void) AttributeTemplate = LLVMGetNamedFunction(mod, "AttributeTemplate"); FuncStrlen = LLVMGetNamedFunction(mod, "strlen"); FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any"); - FuncSlotGetsomeattrs = LLVMGetNamedFunction(mod, "slot_getsomeattrs"); + FuncSlotGetsomeattrsInt = LLVMGetNamedFunction(mod, "slot_getsomeattrs_int"); FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs"); FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal"); FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript"); diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c index 4cee35f582..1725f6d0be 100644 --- a/src/backend/jit/llvm/llvmjit_expr.c +++ b/src/backend/jit/llvm/llvmjit_expr.c @@ -345,7 +345,7 @@ llvm_compile_expr(ExprState *state) params[1] = l_int32_const(op->d.fetch.last_var); LLVMBuildCall(b, - llvm_get_decl(mod, FuncSlotGetsomeattrs), + llvm_get_decl(mod, FuncSlotGetsomeattrsInt), params, lengthof(params), ""); } diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c index 855a6977ee..92d37fb1e5 100644 --- a/src/backend/jit/llvm/llvmjit_types.c +++ b/src/backend/jit/llvm/llvmjit_types.c @@ -97,7 +97,7 @@ void *referenced_functions[] = { strlen, varsize_any, - slot_getsomeattrs, + slot_getsomeattrs_int, slot_getmissingattrs, MakeExpandedObjectReadOnlyInternal, ExecEvalArrayRefSubscript, diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index 7e6b40acb1..9470d38530 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -219,7 +219,6 @@ extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum); extern Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull); -extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum); /* in access/common/heaptuple.c */ extern bool slot_attisnull(TupleTableSlot *slot, int attnum); @@ -227,9 +226,21 @@ extern bool slot_getsysattr(TupleTableSlot *slot, int attnum, Datum *value, bool *isnull); extern Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull); +extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum); #ifndef FRONTEND +/* + * This function forces the entries of the slot's Datum/isnull arrays to be + * valid at least up through the attnum'th entry. + */ +static inline void +slot_getsomeattrs(TupleTableSlot *slot, int attnum) +{ + if (slot->tts_nvalid < attnum) + slot_getsomeattrs_int(slot, attnum); +} + /* * slot_getallattrs * This function forces all the entries of the slot's Datum/isnull diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 3eae5e6831..05c9740bc5 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -77,8 +77,8 @@ extern LLVMTypeRef StructAggStatePerGroupData; extern LLVMValueRef AttributeTemplate; extern LLVMValueRef FuncStrlen; extern LLVMValueRef FuncVarsizeAny; -extern LLVMValueRef FuncSlotGetsomeattrs; extern LLVMValueRef FuncSlotGetmissingattrs; +extern LLVMValueRef FuncSlotGetsomeattrsInt; extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal; extern LLVMValueRef FuncExecEvalArrayRefSubscript; extern LLVMValueRef FuncExecEvalSysVar;