bool hasStage(const StageType type, const PlanStageStats* stats) { if (type == stats->stageType) { return true; } for (size_t i = 0; i < stats->children.size(); ++i) { if (hasStage(type, stats->children[i])) { return true; } } return false; }
SAMRAI_MPI::Status * AsyncCommStage::Member::getStatusPointer() const { if (!hasStage()) { TBOX_ERROR("AssyncCommStage::Member::getStatusPointer():\n" << "Empty stage encountered!\n" << "This probably means the stage Member has not been placed on a stage.\n" << "See documentation for the Membmber's concrete implementation for how\n" << "to place the Member on the stage."); } return d_stage->lookupStatusPointer(d_index_on_stage); }
// static double PlanRanker::scoreTree(const PlanStageStats* stats) { // We start all scores at 1. Our "no plan selected" score is 0 and we want all plans to // be greater than that. double baseScore = 1; // How many "units of work" did the plan perform. Each call to work(...) // counts as one unit, and each NEED_FETCH is penalized as an additional work unit. size_t workUnits = stats->common.works + stats->common.needFetch; // How much did a plan produce? // Range: [0, 1] double productivity = static_cast<double>(stats->common.advanced) / static_cast<double>(workUnits); // Just enough to break a tie. static const double epsilon = 0.0001; // We prefer covered projections. // // We only do this when we have a projection stage because we have so many jstests that // check bounds even when a collscan plan is just as good as the ixscan'd plan :( double noFetchBonus = epsilon; if (hasStage(STAGE_PROJECTION, stats) && hasStage(STAGE_FETCH, stats)) { noFetchBonus = 0; } // In the case of ties, prefer solutions without a blocking sort // to solutions with a blocking sort. double noSortBonus = epsilon; if (hasStage(STAGE_SORT, stats)) { noSortBonus = 0; } // In the case of ties, prefer single index solutions to ixisect. Index // intersection solutions are often slower than single-index solutions // because they require examining a superset of index keys that would be // examined by a single index scan. // // On the other hand, index intersection solutions examine the same // number or fewer of documents. In the case that index intersection // allows us to examine fewer documents, the penalty given to ixisect // can be made up via the no fetch bonus. double noIxisectBonus = epsilon; if (hasStage(STAGE_AND_HASH, stats) || hasStage(STAGE_AND_SORTED, stats)) { noIxisectBonus = 0; } double tieBreakers = noFetchBonus + noSortBonus + noIxisectBonus; double score = baseScore + productivity + tieBreakers; QLOG() << "score (" << score << ") = baseScore(" << baseScore << ")" << " + productivity((" << stats->common.advanced << " advanced)/(" << stats->common.works << " works + " << stats->common.needFetch << " needFetch) = " << productivity << ")" << " + tieBreakers(" << noFetchBonus << " noFetchBonus + " << noSortBonus << " noSortBonus + " << noIxisectBonus << " noIxisectBonus = " << tieBreakers << ")" << endl; if (forceIntersectionPlans) { if (hasStage(STAGE_AND_HASH, stats) || hasStage(STAGE_AND_SORTED, stats)) { // The boost should be >2.001 to make absolutely sure the ixisect plan will win due // to the combination of 1) productivity, 2) eof bonus, and 3) no ixisect bonus. score += 3; QLOG() << "score boosted to " << score << " due to forceIntersectionPlans" << endl; } } return score; }