MCPcopy Create free account
hub / github.com/bytedance/bolt / evalWithMemo

Method evalWithMemo

bolt/expression/Expr.cpp:1202–1299  ·  view source on GitHub ↗

Optimization that attempts to cache results for inputs that are dictionary encoded and use the same base vector between subsequent input batches. Since this hold onto a reference to the base vector and the cached results, it can be memory intensive. Therefore in order to reduce this consumption and ensure it is only employed for cases where it can be useful, it only starts caching result after it

Source from the content-addressed store, hash-verified

1200// it is only employed for cases where it can be useful, it only starts caching
1201// result after it encounters the same base at least twice.
1202void Expr::evalWithMemo(
1203 const SelectivityVector& rows,
1204 EvalCtx& context,
1205 VectorPtr& result) {
1206 VectorPtr base;
1207 distinctFields_[0]->evalSpecialForm(rows, context, base);
1208
1209 if (base.get() != baseOfDictionaryRawPtr_ ||
1210 baseOfDictionaryWeakPtr_.expired()) {
1211 baseOfDictionaryRepeats_ = 0;
1212 baseOfDictionaryWeakPtr_ = base;
1213 baseOfDictionaryRawPtr_ = base.get();
1214 context.releaseVector(baseOfDictionary_);
1215 context.releaseVector(dictionaryCache_);
1216 context.exprSet()->dictionaryCacheTotalSize() -= dictionaryCacheSize_;
1217 dictionaryCacheSize_ = 0;
1218 evalWithNulls(rows, context, result);
1219 return;
1220 }
1221 ++baseOfDictionaryRepeats_;
1222
1223 if (baseOfDictionaryRepeats_ == 1) {
1224 evalWithNulls(rows, context, result);
1225 baseOfDictionary_ = base;
1226 dictionaryCache_ = result;
1227 dictionaryCacheSize_ = dictionaryCache_->retainedSize();
1228 context.exprSet()->dictionaryCacheTotalSize() += dictionaryCacheSize_;
1229 if (!cachedDictionaryIndices_) {
1230 cachedDictionaryIndices_ =
1231 context.execCtx()->getSelectivityVector(rows.end());
1232 }
1233 *cachedDictionaryIndices_ = rows;
1234 context.deselectErrors(*cachedDictionaryIndices_);
1235 return;
1236 }
1237
1238 if (cachedDictionaryIndices_) {
1239 LocalSelectivityVector cachedHolder(context, rows);
1240 auto cached = cachedHolder.get();
1241 BOLT_DCHECK(cached != nullptr);
1242 cached->intersect(*cachedDictionaryIndices_);
1243 if (cached->hasSelections()) {
1244 context.ensureWritable(rows, type(), result);
1245 result->copy(
1246 dictionaryCache_.get(), *cached, nullptr, context.isFinalSelection());
1247 }
1248 }
1249 LocalSelectivityVector uncachedHolder(context, rows);
1250 auto uncached = uncachedHolder.get();
1251 BOLT_DCHECK(uncached != nullptr);
1252 if (cachedDictionaryIndices_) {
1253 uncached->deselect(*cachedDictionaryIndices_);
1254 }
1255 if (uncached->hasSelections()) {
1256 // Fix finalSelection at "rows" if uncached rows is a strict subset to
1257 // avoid losing values not in uncached rows that were copied earlier into
1258 // "result" from the cached rows.
1259 ScopedFinalSelectionSetter scopedFinalSelectionSetter(

Callers

nothing calls this directly

Calls 15

releaseVectorMethod · 0.80
getSelectivityVectorMethod · 0.80
intersectMethod · 0.80
hasSelectionsMethod · 0.80
isFinalSelectionMethod · 0.80
deselectMethod · 0.80
countSelectedMethod · 0.80
addToMemoMethod · 0.80
setAllMethod · 0.80
selectMethod · 0.80
typeEnum · 0.50

Tested by

no test coverage detected