mirror of https://gitee.com/bigwinds/arangodb
fix profiling code (#6190)
This commit is contained in:
parent
102f15bece
commit
fc204a2b3e
|
@ -55,15 +55,6 @@ std::pair<ExecutionState, arangodb::Result> SingletonBlock::initializeCursor(
|
|||
_inputRegisterValues.reset(items->slice(pos, _whitelist));
|
||||
}
|
||||
|
||||
// This could be omitted if ExecutionBlock::initializeCursor() was called
|
||||
// here.
|
||||
if (_profile >= PROFILE_LEVEL_BLOCKS) {
|
||||
// Set block type in per-block statistics.
|
||||
// Intentionally using operator[], which inserts a new element if it can't
|
||||
// find one.
|
||||
_engine->_stats.nodes[getPlanNode()->id()].type = this->getType();
|
||||
}
|
||||
|
||||
_done = false;
|
||||
return {ExecutionState::DONE, TRI_ERROR_NO_ERROR};
|
||||
|
||||
|
@ -458,6 +449,7 @@ std::pair<ExecutionState, std::unique_ptr<AqlItemBlock>> ReturnBlock::getSome(
|
|||
|
||||
auto res = ExecutionBlock::getSomeWithoutRegisterClearout(atMost);
|
||||
if (res.first == ExecutionState::WAITING) {
|
||||
traceGetSomeEnd(nullptr, ExecutionState::WAITING);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,10 +44,6 @@ class SingletonBlock final : public ExecutionBlock {
|
|||
/// above
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SINGLETON;
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<ExecutionState, arangodb::Result> getOrSkipSome(size_t atMost, bool skipping,
|
||||
AqlItemBlock*& result, size_t& skipped) override;
|
||||
|
@ -67,10 +63,6 @@ class FilterBlock final : public ExecutionBlock {
|
|||
std::pair<ExecutionState, arangodb::Result> initializeCursor(
|
||||
AqlItemBlock* items, size_t pos) override final;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::FILTER;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief internal function to actually decide if the document should be used
|
||||
bool takeItem(AqlItemBlock* items, size_t index) const;
|
||||
|
@ -119,10 +111,6 @@ class LimitBlock final : public ExecutionBlock {
|
|||
AqlItemBlock*& result_,
|
||||
size_t& skipped) override;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::LIMIT;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
ExecutionState getHasMoreState() override;
|
||||
|
@ -168,10 +156,6 @@ class ReturnBlock final : public ExecutionBlock {
|
|||
/// returns the id of the register the final result can be found in
|
||||
RegisterId returnInheritedResults();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::RETURN;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief if set to true, the return block will return the AqlItemBlocks it
|
||||
/// gets from above directly. if set to false, the return block will create a
|
||||
|
@ -189,10 +173,6 @@ class NoResultsBlock final : public ExecutionBlock {
|
|||
/// above
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::NO_RESULTS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<ExecutionState, arangodb::Result> getOrSkipSome(
|
||||
size_t atMost, bool skipping, AqlItemBlock*& result,
|
||||
|
|
|
@ -196,6 +196,7 @@ CalculationBlock::getSome(size_t atMost) {
|
|||
|
||||
auto res = ExecutionBlock::getSomeWithoutRegisterClearout(atMost);
|
||||
if (res.first == ExecutionState::WAITING) {
|
||||
traceGetSomeEnd(nullptr, ExecutionState::WAITING);
|
||||
return res;
|
||||
}
|
||||
if (res.second == nullptr) {
|
||||
|
|
|
@ -40,10 +40,6 @@ class CalculationBlock final : public ExecutionBlock {
|
|||
|
||||
~CalculationBlock();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::CALCULATION;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief fill the target register in the item block with a reference to
|
||||
/// another variable
|
||||
|
|
|
@ -1126,7 +1126,6 @@ std::pair<ExecutionState, Result> RemoteBlock::shutdown(int errorCode) {
|
|||
std::pair<ExecutionState, std::unique_ptr<AqlItemBlock>> RemoteBlock::getSome(size_t atMost) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
// For every call we simply forward via HTTP
|
||||
|
||||
traceGetSomeBegin(atMost);
|
||||
|
||||
if (_lastError.fail()) {
|
||||
|
@ -1177,6 +1176,7 @@ std::pair<ExecutionState, std::unique_ptr<AqlItemBlock>> RemoteBlock::getSome(si
|
|||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
traceGetSomeEnd(nullptr, ExecutionState::WAITING);
|
||||
return {ExecutionState::WAITING, nullptr};
|
||||
|
||||
// cppcheck-suppress style
|
||||
|
|
|
@ -121,10 +121,6 @@ class ScatterBlock final : public BlockWithClients {
|
|||
std::vector<std::string> const& shardIds)
|
||||
: BlockWithClients(engine, ep, shardIds) {}
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SCATTER;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
@ -156,10 +152,6 @@ class DistributeBlock final : public BlockWithClients {
|
|||
std::vector<std::string> const& shardIds,
|
||||
Collection const* collection);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::DISTRIBUTE;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
@ -249,10 +241,6 @@ class RemoteBlock final : public ExecutionBlock {
|
|||
/// @brief handleAsyncResult
|
||||
bool handleAsyncResult(ClusterCommResult* result) override;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::REMOTE;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief internal method to send a request
|
||||
/// TODO:Deprecated!
|
||||
|
@ -321,10 +309,6 @@ class UnsortingGatherBlock final : public ExecutionBlock {
|
|||
/// @brief skipSome
|
||||
std::pair<ExecutionState, size_t> skipSome(size_t atMost) override final;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::UNSORTING_GATHER;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief _atDep: currently pulling blocks from _dependencies.at(_atDep),
|
||||
size_t _atDep{};
|
||||
|
@ -374,10 +358,6 @@ class SortingGatherBlock final : public ExecutionBlock {
|
|||
/// @brief skipSome
|
||||
std::pair<ExecutionState, size_t> skipSome(size_t atMost) override final;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SORTING_GATHER;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void clearBuffers() noexcept;
|
||||
|
@ -444,8 +424,6 @@ class SingleRemoteOperationBlock final : public ExecutionBlock {
|
|||
/// @brief skipSome
|
||||
std::pair<ExecutionState, size_t> skipSome(size_t atMost) override final;
|
||||
|
||||
Type getType() const override {return Type::SINGLEOPERATION; }
|
||||
|
||||
private:
|
||||
/// @brief _colectionName: the name of the sharded collection
|
||||
Collection const* _collection;
|
||||
|
|
|
@ -95,10 +95,6 @@ class SortedCollectBlock final : public ExecutionBlock {
|
|||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SORTED_COLLECT;
|
||||
}
|
||||
|
||||
private:
|
||||
std::pair<ExecutionState, Result> getOrSkipSome(size_t atMost, bool skipping,
|
||||
AqlItemBlock*& result,
|
||||
|
@ -146,10 +142,6 @@ class HashedCollectBlock final : public ExecutionBlock {
|
|||
HashedCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||
~HashedCollectBlock() final;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::HASHED_COLLECT;
|
||||
}
|
||||
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items,
|
||||
size_t pos) override;
|
||||
|
||||
|
@ -188,10 +180,6 @@ class DistinctCollectBlock final : public ExecutionBlock {
|
|||
DistinctCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||
~DistinctCollectBlock();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::DISTINCT_COLLECT;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
@ -214,10 +202,6 @@ class CountCollectBlock final : public ExecutionBlock {
|
|||
public:
|
||||
CountCollectBlock(ExecutionEngine*, CollectNode const*);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::COUNT_COLLECT;
|
||||
}
|
||||
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
std::pair<ExecutionState, Result> getOrSkipSome(size_t atMost, bool skipping,
|
||||
|
|
|
@ -46,10 +46,6 @@ class EnumerateCollectionBlock final : public ExecutionBlock, public DocumentPro
|
|||
EnumerateCollectionBlock(ExecutionEngine* engine,
|
||||
EnumerateCollectionNode const* ep);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::ENUMERATE_COLLECTION;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -39,11 +39,6 @@ class EnumerateListBlock final : public ExecutionBlock {
|
|||
EnumerateListBlock(ExecutionEngine*, EnumerateListNode const*);
|
||||
~EnumerateListBlock();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::ENUMERATE_LIST;
|
||||
}
|
||||
|
||||
// here we release our docs from this collection
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
std::pair<ExecutionState, std::unique_ptr<AqlItemBlock>> getSome(
|
||||
|
|
|
@ -54,69 +54,6 @@ static std::string const& stateToString(ExecutionState state) {
|
|||
return unknownString;
|
||||
}
|
||||
|
||||
struct ExecutionBlockTypeHash {
|
||||
size_t operator()(ExecutionBlock::Type value) const noexcept {
|
||||
typedef std::underlying_type<decltype(value)>::type UnderlyingType;
|
||||
return std::hash<UnderlyingType>()(UnderlyingType(value));
|
||||
}
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, arangodb::aql::ExecutionBlock::Type> const NamesToBlockTypeMap = {
|
||||
{ "-undefined-", arangodb::aql::ExecutionBlock::Type::_UNDEFINED},
|
||||
{ "CalculationBlock", arangodb::aql::ExecutionBlock::Type::CALCULATION},
|
||||
{ "CountCollectBlock", arangodb::aql::ExecutionBlock::Type::COUNT_COLLECT},
|
||||
{ "DistinctCollectBlock", arangodb::aql::ExecutionBlock::Type::DISTINCT_COLLECT},
|
||||
{ "EnumerateCollectionBlock", arangodb::aql::ExecutionBlock::Type::ENUMERATE_COLLECTION},
|
||||
{ "EnumerateListBlock", arangodb::aql::ExecutionBlock::Type::ENUMERATE_LIST},
|
||||
{ "FilterBlock", arangodb::aql::ExecutionBlock::Type::FILTER},
|
||||
{ "HashedCollectBlock", arangodb::aql::ExecutionBlock::Type::HASHED_COLLECT},
|
||||
{ "IndexBlock", arangodb::aql::ExecutionBlock::Type::INDEX},
|
||||
{ "LimitBlock", arangodb::aql::ExecutionBlock::Type::LIMIT},
|
||||
{ "NoResultsBlock", arangodb::aql::ExecutionBlock::Type::NO_RESULTS},
|
||||
{ "RemoteBlock", arangodb::aql::ExecutionBlock::Type::REMOTE},
|
||||
{ "ReturnBlock", arangodb::aql::ExecutionBlock::Type::RETURN},
|
||||
{ "ShortestPathBlock", arangodb::aql::ExecutionBlock::Type::SHORTEST_PATH},
|
||||
{ "SingletonBlock", arangodb::aql::ExecutionBlock::Type::SINGLETON},
|
||||
{ "SingleOperationBlock", arangodb::aql::ExecutionBlock::Type::SINGLEOPERATION},
|
||||
{ "SortBlock", arangodb::aql::ExecutionBlock::Type::SORT},
|
||||
{ "SortedCollectBlock", arangodb::aql::ExecutionBlock::Type::SORTED_COLLECT},
|
||||
{ "SortingGatherBlock", arangodb::aql::ExecutionBlock::Type::SORTING_GATHER},
|
||||
{ "SubqueryBlock", arangodb::aql::ExecutionBlock::Type::SUBQUERY},
|
||||
{ "TraversalBlock", arangodb::aql::ExecutionBlock::Type::TRAVERSAL},
|
||||
{ "UnsortingGatherBlock", arangodb::aql::ExecutionBlock::Type::UNSORTING_GATHER},
|
||||
{ "RemoveBlock", arangodb::aql::ExecutionBlock::Type::REMOVE},
|
||||
{ "InsertBlock", arangodb::aql::ExecutionBlock::Type::INSERT},
|
||||
{ "UpdateBlock", arangodb::aql::ExecutionBlock::Type::UPDATE},
|
||||
{ "ReplaceBlock", arangodb::aql::ExecutionBlock::Type::REPLACE},
|
||||
{ "UpsertBlock", arangodb::aql::ExecutionBlock::Type::UPSERT},
|
||||
{ "ScatterBlock", arangodb::aql::ExecutionBlock::Type::SCATTER},
|
||||
{ "DistributeBlock", arangodb::aql::ExecutionBlock::Type::DISTRIBUTE},
|
||||
#ifdef USE_IRESEARCH
|
||||
{ "IResearchViewBlock", arangodb::aql::ExecutionBlock::Type::IRESEARCH_VIEW},
|
||||
{ "IResearchViewOrderedBlock", arangodb::aql::ExecutionBlock::Type::IRESEARCH_VIEW_ORDERED},
|
||||
{ "IResearchViewUnorderedBlock", arangodb::aql::ExecutionBlock::Type::IRESEARCH_VIEW_UNORDERED}
|
||||
#endif
|
||||
};
|
||||
|
||||
std::unordered_map<
|
||||
arangodb::aql::ExecutionBlock::Type,
|
||||
std::reference_wrapper<const std::string>,
|
||||
ExecutionBlockTypeHash
|
||||
> blockTypeToNamesMap;
|
||||
|
||||
struct BlockTypeToNameMapInitializer {
|
||||
BlockTypeToNameMapInitializer() {
|
||||
blockTypeToNamesMap.reserve(NamesToBlockTypeMap.size());
|
||||
std::for_each(NamesToBlockTypeMap.begin(),
|
||||
NamesToBlockTypeMap.end(),
|
||||
[](std::pair<std::string const&, arangodb::aql::ExecutionBlock::Type> const& p) {
|
||||
blockTypeToNamesMap.emplace(p.second, p.first);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} initializeBlockTypeToNameMap;
|
||||
|
||||
} // namespace
|
||||
|
||||
ExecutionBlock::ExecutionBlock(ExecutionEngine* engine, ExecutionNode const* ep)
|
||||
|
@ -206,13 +143,6 @@ std::pair<ExecutionState, arangodb::Result> ExecutionBlock::initializeCursor(
|
|||
_skipped = 0;
|
||||
_collector.clear();
|
||||
|
||||
if (_profile >= PROFILE_LEVEL_BLOCKS) {
|
||||
// Set block type in per-block statistics.
|
||||
// Intentionally using operator[], which inserts a new element if it can't
|
||||
// find one.
|
||||
_engine->_stats.nodes[getPlanNode()->id()].type = this->getType();
|
||||
}
|
||||
|
||||
TRI_ASSERT(getHasMoreState() == ExecutionState::HASMORE);
|
||||
TRI_ASSERT(_dependencyPos == _dependencies.end());
|
||||
return {ExecutionState::DONE, TRI_ERROR_NO_ERROR};
|
||||
|
@ -255,7 +185,9 @@ std::pair<ExecutionState, Result> ExecutionBlock::shutdown(int errorCode) {
|
|||
// Trace the start of a getSome call
|
||||
void ExecutionBlock::traceGetSomeBegin(size_t atMost) {
|
||||
if (_profile >= PROFILE_LEVEL_BLOCKS) {
|
||||
_getSomeBegin = TRI_microtime();
|
||||
if (_getSomeBegin == 0) {
|
||||
_getSomeBegin = TRI_microtime();
|
||||
}
|
||||
if (_profile >= PROFILE_LEVEL_TRACE_1) {
|
||||
auto node = getPlanNode();
|
||||
LOG_TOPIC(INFO, Logger::QUERIES)
|
||||
|
@ -267,15 +199,18 @@ void ExecutionBlock::traceGetSomeBegin(size_t atMost) {
|
|||
}
|
||||
|
||||
// Trace the end of a getSome call, potentially with result
|
||||
void ExecutionBlock::traceGetSomeEnd(AqlItemBlock const* result, ExecutionState state) const {
|
||||
void ExecutionBlock::traceGetSomeEnd(AqlItemBlock const* result, ExecutionState state) {
|
||||
TRI_ASSERT(result != nullptr || state != ExecutionState::HASMORE);
|
||||
if (_profile >= PROFILE_LEVEL_BLOCKS) {
|
||||
ExecutionNode const* en = getPlanNode();
|
||||
ExecutionStats::Node stats;
|
||||
stats.calls = 1;
|
||||
stats.items = result != nullptr ? result->size() : 0;
|
||||
stats.runtime = TRI_microtime() - _getSomeBegin;
|
||||
stats.type = getType();
|
||||
if (state != ExecutionState::WAITING) {
|
||||
stats.runtime = TRI_microtime() - _getSomeBegin;
|
||||
_getSomeBegin = 0;
|
||||
}
|
||||
|
||||
auto it = _engine->_stats.nodes.find(en->id());
|
||||
if (it != _engine->_stats.nodes.end()) {
|
||||
it->second += stats;
|
||||
|
@ -695,24 +630,3 @@ RegisterId ExecutionBlock::getNrOutputRegisters() const {
|
|||
|
||||
return outputNrRegs;
|
||||
}
|
||||
|
||||
std::string ExecutionBlock::typeToString(ExecutionBlock::Type type) {
|
||||
auto got = ::blockTypeToNamesMap.find(type);
|
||||
if (got == ::blockTypeToNamesMap.end()) {
|
||||
// to please compiler in non-maintainer mode
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||
std::string("when converting ExecutionBlock::Type to string: got invalid type"));
|
||||
}
|
||||
return got->second;
|
||||
}
|
||||
|
||||
ExecutionBlock::Type ExecutionBlock::typeFromString(std::string const& type) {
|
||||
auto got = ::NamesToBlockTypeMap.find(type);
|
||||
if (got == ::NamesToBlockTypeMap.end()) {
|
||||
// to please compiler in non-maintainer mode
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
||||
std::string("when converting string to ExecutionBlock::Type: got invalid string '" + type + "'"));
|
||||
return arangodb::aql::ExecutionBlock::Type::_UNDEFINED;
|
||||
}
|
||||
return got->second;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@ class Methods;
|
|||
namespace aql {
|
||||
class AqlItemBlock;
|
||||
class ExecutionEngine;
|
||||
struct QueryProfile;
|
||||
|
||||
class ExecutionBlock {
|
||||
public:
|
||||
|
@ -80,54 +79,6 @@ class ExecutionBlock {
|
|||
ExecutionBlock(ExecutionBlock const&) = delete;
|
||||
ExecutionBlock operator=(ExecutionBlock const&) = delete;
|
||||
|
||||
/// @brief type of the block. only the blocks actually instantiated are
|
||||
// needed, so e.g. ModificationBlock or ExecutionBlock are omitted.
|
||||
enum class Type {
|
||||
_UNDEFINED,
|
||||
CALCULATION,
|
||||
COUNT_COLLECT,
|
||||
DISTINCT_COLLECT,
|
||||
ENUMERATE_COLLECTION,
|
||||
ENUMERATE_LIST,
|
||||
FILTER,
|
||||
HASHED_COLLECT,
|
||||
INDEX,
|
||||
LIMIT,
|
||||
NO_RESULTS,
|
||||
REMOTE,
|
||||
RETURN,
|
||||
SHORTEST_PATH,
|
||||
SINGLETON,
|
||||
SINGLEOPERATION,
|
||||
SORT,
|
||||
SORTED_COLLECT,
|
||||
SORTING_GATHER,
|
||||
SUBQUERY,
|
||||
TRAVERSAL,
|
||||
UNSORTING_GATHER,
|
||||
REMOVE,
|
||||
INSERT,
|
||||
UPDATE,
|
||||
REPLACE,
|
||||
UPSERT,
|
||||
SCATTER,
|
||||
DISTRIBUTE,
|
||||
#ifdef USE_IRESEARCH
|
||||
IRESEARCH_VIEW,
|
||||
IRESEARCH_VIEW_ORDERED,
|
||||
IRESEARCH_VIEW_UNORDERED,
|
||||
#endif
|
||||
};
|
||||
// omitted in this list are (because):
|
||||
// WaitingExecutionBlockMock (mock)
|
||||
// ExecutionBlockMock (mock)
|
||||
// ModificationBlock (insert, update, etc.)
|
||||
// BlockWithClients (scatter, distribute)
|
||||
// IResearchViewBlockBase (IResearchView*)
|
||||
|
||||
static std::string typeToString(Type type);
|
||||
static Type typeFromString(std::string const& type);
|
||||
|
||||
public:
|
||||
/// @brief batch size value
|
||||
static constexpr inline size_t DefaultBatchSize() { return 1000; }
|
||||
|
@ -186,7 +137,7 @@ class ExecutionBlock {
|
|||
size_t atMost);
|
||||
|
||||
void traceGetSomeBegin(size_t atMost);
|
||||
void traceGetSomeEnd(AqlItemBlock const*, ExecutionState state) const;
|
||||
void traceGetSomeEnd(AqlItemBlock const*, ExecutionState state);
|
||||
|
||||
/// @brief skipSome, skips some more items, semantic is as follows: not
|
||||
/// more than atMost items may be skipped. The method tries to
|
||||
|
@ -213,8 +164,6 @@ class ExecutionBlock {
|
|||
|
||||
RegisterId getNrOutputRegisters() const;
|
||||
|
||||
virtual Type getType() const {return Type::_UNDEFINED;}
|
||||
|
||||
protected:
|
||||
/// @brief request an AqlItemBlock from the memory manager
|
||||
AqlItemBlock* requestBlock(size_t nrItems, RegisterId nrRegs);
|
||||
|
|
|
@ -51,16 +51,11 @@ void ExecutionStats::toVelocyPack(VPackBuilder& builder, bool reportFullCount) c
|
|||
if (!nodes.empty()) {
|
||||
builder.add("nodes", VPackValue(VPackValueType::Array));
|
||||
for (std::pair<size_t const, ExecutionStats::Node> const& pair : nodes) {
|
||||
// the block type should always be set here
|
||||
TRI_ASSERT(pair.second.type != ExecutionBlock::Type::_UNDEFINED);
|
||||
|
||||
builder.openObject();
|
||||
builder.add("id", VPackValue(pair.first));
|
||||
builder.add("calls", VPackValue(pair.second.calls));
|
||||
builder.add("items", VPackValue(pair.second.items));
|
||||
builder.add("runtime", VPackValue(pair.second.runtime));
|
||||
builder.add("blockType",
|
||||
VPackValue(ExecutionBlock::typeToString(pair.second.type)));
|
||||
builder.close();
|
||||
}
|
||||
builder.close();
|
||||
|
@ -140,8 +135,6 @@ ExecutionStats::ExecutionStats(VPackSlice const& slice)
|
|||
node.calls = val.get("calls").getNumber<size_t>();
|
||||
node.items = val.get("items").getNumber<size_t>();
|
||||
node.runtime = val.get("runtime").getNumber<double>();
|
||||
node.type =
|
||||
ExecutionBlock::typeFromString(val.get("blockType").copyString());
|
||||
nodes.emplace(nid, node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,10 +47,7 @@ struct ExecutionStats {
|
|||
size_t calls = 0;
|
||||
size_t items = 0;
|
||||
double runtime = 0;
|
||||
ExecutionBlock::Type type = ExecutionBlock::Type::_UNDEFINED;
|
||||
ExecutionStats::Node& operator+=(ExecutionStats::Node const& other) {
|
||||
// both operands should be the same block type
|
||||
TRI_ASSERT(type == other.type);
|
||||
calls += other.calls;
|
||||
items += other.items;
|
||||
runtime += other.runtime;
|
||||
|
|
|
@ -61,10 +61,6 @@ class IndexBlock final : public ExecutionBlock, public DocumentProducingBlock {
|
|||
|
||||
~IndexBlock();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::INDEX;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor, here we release our docs from this collection
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -109,10 +109,6 @@ class RemoveBlock : public ModificationBlock {
|
|||
RemoveBlock(ExecutionEngine*, RemoveNode const*);
|
||||
~RemoveBlock() = default;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::REMOVE;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief the actual work horse for removing data
|
||||
std::unique_ptr<AqlItemBlock> work() override final;
|
||||
|
@ -123,10 +119,6 @@ class InsertBlock : public ModificationBlock {
|
|||
InsertBlock(ExecutionEngine*, InsertNode const*);
|
||||
~InsertBlock() = default;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::INSERT;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief the actual work horse for inserting data
|
||||
std::unique_ptr<AqlItemBlock> work() override final;
|
||||
|
@ -137,10 +129,6 @@ class UpdateBlock : public ModificationBlock {
|
|||
UpdateBlock(ExecutionEngine*, UpdateNode const*);
|
||||
~UpdateBlock() = default;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::UPDATE;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief the actual work horse for updating data
|
||||
std::unique_ptr<AqlItemBlock> work() override final;
|
||||
|
@ -151,10 +139,6 @@ class ReplaceBlock : public ModificationBlock {
|
|||
ReplaceBlock(ExecutionEngine*, ReplaceNode const*);
|
||||
~ReplaceBlock() = default;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::REPLACE;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief the actual work horse for replacing data
|
||||
std::unique_ptr<AqlItemBlock> work() override final;
|
||||
|
@ -165,10 +149,6 @@ class UpsertBlock : public ModificationBlock {
|
|||
UpsertBlock(ExecutionEngine*, UpsertNode const*);
|
||||
~UpsertBlock() = default;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::UPSERT;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief the actual work horse for updating data
|
||||
std::unique_ptr<AqlItemBlock> work() override final;
|
||||
|
|
|
@ -45,10 +45,6 @@ class ShortestPathBlock final : public ExecutionBlock {
|
|||
public:
|
||||
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SHORTEST_PATH;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -42,10 +42,6 @@ class SortBlock final : public ExecutionBlock {
|
|||
|
||||
~SortBlock();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SORT;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor, could be called multiple times
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -39,10 +39,6 @@ class SubqueryBlock final : public ExecutionBlock {
|
|||
SubqueryBlock(ExecutionEngine*, SubqueryNode const*, ExecutionBlock*);
|
||||
~SubqueryBlock() = default;
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::SUBQUERY;
|
||||
}
|
||||
|
||||
/// @brief getSome
|
||||
std::pair<ExecutionState, std::unique_ptr<AqlItemBlock>> getSome(
|
||||
size_t atMost) override final;
|
||||
|
|
|
@ -43,10 +43,6 @@ class TraversalBlock final : public ExecutionBlock {
|
|||
|
||||
~TraversalBlock();
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::TRAVERSAL;
|
||||
}
|
||||
|
||||
/// @brief initializeCursor
|
||||
std::pair<ExecutionState, Result> initializeCursor(AqlItemBlock* items, size_t pos) override;
|
||||
|
||||
|
|
|
@ -263,11 +263,13 @@ IResearchViewBlockBase::getSome(size_t atMost) {
|
|||
size_t const toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
auto upstreamRes = ExecutionBlock::getBlock(toFetch);
|
||||
if (upstreamRes.first == ExecutionState::WAITING) {
|
||||
traceGetSomeEnd(nullptr, ExecutionState::WAITING);
|
||||
return {upstreamRes.first, nullptr};
|
||||
}
|
||||
_upstreamState = upstreamRes.first;
|
||||
if (!upstreamRes.second) {
|
||||
_done = true;
|
||||
traceGetSomeEnd(nullptr, ExecutionState::DONE);
|
||||
return {ExecutionState::DONE, nullptr};
|
||||
}
|
||||
_pos = 0; // this is in the first block
|
||||
|
|
|
@ -139,10 +139,6 @@ class IResearchViewUnorderedBlock : public IResearchViewBlockBase {
|
|||
IResearchViewNode const& node
|
||||
);
|
||||
|
||||
Type getType() const override {
|
||||
return Type::IRESEARCH_VIEW_UNORDERED;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void reset() override final {
|
||||
IResearchViewBlockBase::reset();
|
||||
|
@ -176,10 +172,6 @@ class IResearchViewBlock final : public IResearchViewUnorderedBlock {
|
|||
IResearchViewNode const& node
|
||||
);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::IRESEARCH_VIEW;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool next(
|
||||
aql::AqlItemBlock& res,
|
||||
|
@ -208,10 +200,6 @@ class IResearchViewOrderedBlock final : public IResearchViewBlockBase {
|
|||
IResearchViewNode const& node
|
||||
);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::IRESEARCH_VIEW_ORDERED;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void reset() override {
|
||||
IResearchViewBlockBase::reset();
|
||||
|
|
|
@ -684,11 +684,11 @@ function processQuery (query, explain) {
|
|||
maxCallsLen = String(n.calls).length;
|
||||
}
|
||||
if (String(n.items).length > maxItemsLen) {
|
||||
maxCallsLen = String(n.items).length;
|
||||
maxItemsLen = String(n.items).length;
|
||||
}
|
||||
let l = String(nodes[n.id].runtime.toFixed(3)).length;
|
||||
if (l > maxRuntimeLen) {
|
||||
maxCallsLen = l;
|
||||
maxRuntimeLen = l;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1424,15 +1424,13 @@ function processQuery (query, explain) {
|
|||
return keyword('DISTRIBUTE');
|
||||
case 'ScatterNode':
|
||||
return keyword('SCATTER');
|
||||
case 'ScatterViewNode':
|
||||
return keyword('SCATTER VIEW');
|
||||
case 'GatherNode':
|
||||
return keyword('GATHER') + ' ' + node.elements.map(function (node) {
|
||||
if (node.path && node.path.length) {
|
||||
return variableName(node.inVariable) + node.path.map(function(n) { return '.' + attribute(n); }) + ' ' + keyword(node.ascending ? 'ASC' : 'DESC');
|
||||
}
|
||||
return variableName(node.inVariable) + ' ' + keyword(node.ascending ? 'ASC' : 'DESC');
|
||||
}).join(', ');
|
||||
}).join(', ') + ' ' + annotation('/* sort mode: ' + node.sortmode + ' */');
|
||||
}
|
||||
|
||||
return 'unhandled node type (' + node.type + ')';
|
||||
|
|
|
@ -77,36 +77,36 @@ const nodeTypesList = [
|
|||
SubqueryNode, TraversalNode, UpdateNode, UpsertNode
|
||||
];
|
||||
|
||||
const CalculationBlock = 'CalculationBlock';
|
||||
const CountCollectBlock = 'CountCollectBlock';
|
||||
const DistinctCollectBlock = 'DistinctCollectBlock';
|
||||
const EnumerateCollectionBlock = 'EnumerateCollectionBlock';
|
||||
const EnumerateListBlock = 'EnumerateListBlock';
|
||||
const FilterBlock = 'FilterBlock';
|
||||
const HashedCollectBlock = 'HashedCollectBlock';
|
||||
const IndexBlock = 'IndexBlock';
|
||||
const LimitBlock = 'LimitBlock';
|
||||
const NoResultsBlock = 'NoResultsBlock';
|
||||
const RemoteBlock = 'RemoteBlock';
|
||||
const ReturnBlock = 'ReturnBlock';
|
||||
const ShortestPathBlock = 'ShortestPathBlock';
|
||||
const SingletonBlock = 'SingletonBlock';
|
||||
const SortBlock = 'SortBlock';
|
||||
const SortedCollectBlock = 'SortedCollectBlock';
|
||||
const SortingGatherBlock = 'SortingGatherBlock';
|
||||
const SubqueryBlock = 'SubqueryBlock';
|
||||
const TraversalBlock = 'TraversalBlock';
|
||||
const UnsortingGatherBlock = 'UnsortingGatherBlock';
|
||||
const RemoveBlock = 'RemoveBlock';
|
||||
const InsertBlock = 'InsertBlock';
|
||||
const UpdateBlock = 'UpdateBlock';
|
||||
const ReplaceBlock = 'ReplaceBlock';
|
||||
const UpsertBlock = 'UpsertBlock';
|
||||
const ScatterBlock = 'ScatterBlock';
|
||||
const DistributeBlock = 'DistributeBlock';
|
||||
const IResearchViewUnorderedBlock = 'IResearchViewUnorderedBlock';
|
||||
const IResearchViewBlock = 'IResearchViewBlock';
|
||||
const IResearchViewOrderedBlock = 'IResearchViewOrderedBlock';
|
||||
const CalculationBlock = 'CalculationNode';
|
||||
const CountCollectBlock = 'CountCollectNode';
|
||||
const DistinctCollectBlock = 'DistinctCollectNode';
|
||||
const EnumerateCollectionBlock = 'EnumerateCollectionNode';
|
||||
const EnumerateListBlock = 'EnumerateListNode';
|
||||
const FilterBlock = 'FilterNode';
|
||||
const HashedCollectBlock = 'HashedCollectNode';
|
||||
const IndexBlock = 'IndexNode';
|
||||
const LimitBlock = 'LimitNode';
|
||||
const NoResultsBlock = 'NoResultsNode';
|
||||
const RemoteBlock = 'RemoteNode';
|
||||
const ReturnBlock = 'ReturnNode';
|
||||
const ShortestPathBlock = 'ShortestPathNode';
|
||||
const SingletonBlock = 'SingletonNode';
|
||||
const SortBlock = 'SortNode';
|
||||
const SortedCollectBlock = 'SortedCollectNode';
|
||||
const SortingGatherBlock = 'SortingGatherNode';
|
||||
const SubqueryBlock = 'SubqueryNode';
|
||||
const TraversalBlock = 'TraversalNode';
|
||||
const UnsortingGatherBlock = 'UnsortingGatherNode';
|
||||
const RemoveBlock = 'RemoveNode';
|
||||
const InsertBlock = 'InsertNode';
|
||||
const UpdateBlock = 'UpdateNode';
|
||||
const ReplaceBlock = 'ReplaceNode';
|
||||
const UpsertBlock = 'UpsertNode';
|
||||
const ScatterBlock = 'ScatterNode';
|
||||
const DistributeBlock = 'DistributeNode';
|
||||
const IResearchViewUnorderedBlock = 'IResearchUnorderedViewNode';
|
||||
const IResearchViewBlock = 'IResearchViewNode';
|
||||
const IResearchViewOrderedBlock = 'IResearchOrderedViewNode';
|
||||
|
||||
const blockTypesList = [
|
||||
CalculationBlock, CountCollectBlock, DistinctCollectBlock,
|
||||
|
@ -119,6 +119,33 @@ const blockTypesList = [
|
|||
IResearchViewBlock, IResearchViewOrderedBlock
|
||||
];
|
||||
|
||||
let translateType = function(nodes, node) {
|
||||
let types = {};
|
||||
nodes.forEach(function(node) {
|
||||
let type = node.type;
|
||||
if (type === 'CollectNode') {
|
||||
if (node.collectOptions.method === 'sorted') {
|
||||
type = 'SortedCollectNode';
|
||||
} else if (node.collectOptions.method === 'hash') {
|
||||
type = 'HashedCollectNode';
|
||||
} else if (node.collectOptions.method === 'distinct') {
|
||||
type = 'DistinctCollectNode';
|
||||
} else if (node.collectOptions.method === 'count') {
|
||||
type = 'CountCollectNode';
|
||||
}
|
||||
} else if (node.type === 'GatherNode') {
|
||||
if (node.sortmode === 'minelement' || node.sortmode === 'heap') {
|
||||
type = 'SortingGatherNode';
|
||||
} else {
|
||||
type = 'UnsortingGatherNode';
|
||||
}
|
||||
}
|
||||
types[node.id] = type;
|
||||
});
|
||||
|
||||
return types[node.id];
|
||||
};
|
||||
|
||||
/// @brief check that numbers in actual are in the range specified by
|
||||
/// expected. Each element in expected may either be
|
||||
/// - a number, for an exact match;
|
||||
|
@ -161,11 +188,15 @@ function zipPlanNodesIntoStatsNodes (profile) {
|
|||
},
|
||||
{}
|
||||
);
|
||||
|
||||
|
||||
// Note: We need to take the order plan.nodes here, not stats.nodes,
|
||||
// as stats.nodes is sorted by id.
|
||||
return profile.plan.nodes.map(node => (
|
||||
{ id: node.id, fromStats: statsNodesById[node.id], fromPlan: node }
|
||||
{
|
||||
id: node.id,
|
||||
type: translateType(profile.plan.nodes, node),
|
||||
fromStats: statsNodesById[node.id], fromPlan: node
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -174,8 +205,7 @@ function getCompactStatsNodes (profile) {
|
|||
// of the plan, not from the stats (which is sorted by id).
|
||||
return zipPlanNodesIntoStatsNodes(profile).map(
|
||||
node => ({
|
||||
// type: node.fromPlan.type,
|
||||
type: node.fromStats.blockType,
|
||||
type: translateType(profile.plan.nodes, node),
|
||||
calls: node.fromStats.calls,
|
||||
items: node.fromStats.items,
|
||||
})
|
||||
|
@ -195,7 +225,7 @@ function getStatsNodesWithId (profile) {
|
|||
return profile.stats.nodes.map(
|
||||
node => ({
|
||||
id: node.id,
|
||||
blockType: node.blockType,
|
||||
type: node.type,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -422,7 +452,6 @@ function assertStatsNodesMatchPlanNodes (profile) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function assertNodesItemsAndCalls (expected, actual, details = {}) {
|
||||
|
||||
// assert node types first
|
||||
assert.assertEqual(
|
||||
expected.map(node => node.type),
|
||||
|
@ -528,8 +557,6 @@ function createBinaryTree (vertexCol, edgeCol, numVertices) {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
exports.colName = colName;
|
||||
exports.edgeColName = edgeColName;
|
||||
exports.defaultBatchSize = defaultBatchSize;
|
||||
|
|
|
@ -486,8 +486,7 @@ function ahuacatlProfilerTestSuite () {
|
|||
node => (
|
||||
node.fromStats ?
|
||||
{
|
||||
// type: node.fromPlan.type,
|
||||
type: node.fromStats.blockType,
|
||||
type: node.type,
|
||||
calls: node.fromStats.calls,
|
||||
items: node.fromStats.items,
|
||||
} : {})
|
||||
|
|
|
@ -86,10 +86,6 @@ class ExecutionBlockMock final : public arangodb::aql::ExecutionBlock {
|
|||
arangodb::aql::ExecutionNode const& node
|
||||
);
|
||||
|
||||
Type getType() const override final {
|
||||
return Type::_UNDEFINED;
|
||||
}
|
||||
|
||||
// here we release our docs from this collection
|
||||
std::pair<arangodb::aql::ExecutionState, arangodb::Result> initializeCursor(
|
||||
arangodb::aql::AqlItemBlock* items, size_t pos) override;
|
||||
|
|
Loading…
Reference in New Issue