From e6b39a8fe89aea87edd5997320ebb78580e98e16 Mon Sep 17 00:00:00 2001 From: jsteemann Date: Sat, 23 Apr 2016 11:20:52 +0200 Subject: [PATCH] added simple infrastructure for timing --- arangod/V8Server/v8-collection.cpp | 19 +++++++- arangod/V8Server/v8-vocbase.cpp | 39 +++++++++++++++++ lib/Basics/Timers.cpp | 65 ++++++++++++++++++++++++++++ lib/Basics/Timers.h | 69 ++++++++++++++++++++++++++++++ lib/CMakeLists.txt | 1 + 5 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 lib/Basics/Timers.cpp create mode 100644 lib/Basics/Timers.h diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 10bc3c9d35..b86f9c2eb9 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -23,6 +23,7 @@ #include "v8-collection.h" #include "Aql/Query.h" +#include "Basics/Timers.h" #include "Basics/Utf8Helper.h" #include "Basics/conversions.h" #include "Basics/ScopeGuard.h" @@ -2109,6 +2110,8 @@ static void JS_InsertVocbaseCol( TRI_V8_TRY_CATCH_BEGIN(isolate); v8::HandleScope scope(isolate); + TIMER_START(JS_INSERT_ALL); + auto collection = TRI_UnwrapClass(args.Holder(), WRP_VOCBASE_COL_TYPE); if (collection == nullptr) { @@ -2174,6 +2177,8 @@ static void JS_InsertVocbaseCol( // invalid value type. must be a document TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID); } + + TIMER_START(JS_INSERT_V8_TO_VPACK); // copy default options (and set exclude handler in copy) VPackOptions vpackOptions = VPackOptions::Defaults; @@ -2216,6 +2221,8 @@ static void JS_InsertVocbaseCol( } else { doOneDocument(payload); } + + TIMER_STOP(JS_INSERT_V8_TO_VPACK); // load collection auto transactionContext = std::make_shared(collection->_vocbase, true); @@ -2246,8 +2253,16 @@ static void JS_InsertVocbaseCol( VPackSlice resultSlice = result.slice(); - TRI_V8_RETURN(TRI_VPackToV8(isolate, resultSlice, - transactionContext->getVPackOptions())); + TIMER_START(JS_INSERT_VPACK_TO_V8); + + auto v8Result = TRI_VPackToV8(isolate, resultSlice, + transactionContext->getVPackOptions()); + + TIMER_STOP(JS_INSERT_VPACK_TO_V8); + + TIMER_STOP(JS_INSERT_ALL); + + TRI_V8_RETURN(v8Result); TRI_V8_TRY_CATCH_END } diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 25254bba47..76b16f450b 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -41,6 +41,7 @@ #include "Aql/QueryRegistry.h" #include "Basics/MutexLocker.h" #include "Basics/ScopeGuard.h" +#include "Basics/Timers.h" #include "Basics/Utf8Helper.h" #include "Basics/conversions.h" #include "Basics/tri-strings.h" @@ -3331,6 +3332,36 @@ static void JS_ListEndpoints(v8::FunctionCallbackInfo const& args) { TRI_V8_TRY_CATCH_END } +static void JS_ClearTimers(v8::FunctionCallbackInfo const& args) { + TRI_V8_TRY_CATCH_BEGIN(isolate); + v8::HandleScope scope(isolate); + + arangodb::basics::Timers::clear(); + + TRI_V8_RETURN(v8::Undefined(isolate)); + TRI_V8_TRY_CATCH_END +} + +static void JS_GetTimers(v8::FunctionCallbackInfo const& args) { + TRI_V8_TRY_CATCH_BEGIN(isolate); + v8::HandleScope scope(isolate); + + v8::Handle totals = v8::Object::New(isolate); + v8::Handle counts = v8::Object::New(isolate); + + for (auto& it : arangodb::basics::Timers::get()) { + totals->ForceSet(TRI_V8_STD_STRING(it.first), v8::Number::New(isolate, it.second.first)); + counts->ForceSet(TRI_V8_STD_STRING(it.first), v8::Number::New(isolate, it.second.second)); + } + + v8::Handle result = v8::Object::New(isolate); + result->ForceSet(TRI_V8_ASCII_STRING("totals"), totals); + result->ForceSet(TRI_V8_ASCII_STRING("counts"), counts); + + TRI_V8_RETURN(result); + TRI_V8_TRY_CATCH_END +} + //////////////////////////////////////////////////////////////////////////////// /// @brief return the private WRP_VOCBASE_COL_TYPE value //////////////////////////////////////////////////////////////////////////////// @@ -3580,6 +3611,14 @@ void TRI_InitV8VocBridge(v8::Isolate* isolate, v8::Handle context, TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("Debug"), JS_Debug, true); + + TRI_AddGlobalFunctionVocbase(isolate, context, + TRI_V8_ASCII_STRING("CLEAR_TIMERS"), + JS_ClearTimers, true); + + TRI_AddGlobalFunctionVocbase(isolate, context, + TRI_V8_ASCII_STRING("GET_TIMERS"), + JS_GetTimers, true); // ............................................................................. // create global variables diff --git a/lib/Basics/Timers.cpp b/lib/Basics/Timers.cpp new file mode 100644 index 0000000000..c7b157db86 --- /dev/null +++ b/lib/Basics/Timers.cpp @@ -0,0 +1,65 @@ +//////////////////////////////////////////////////////////////////////////////// +/// DISCLAIMER +/// +/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +//////////////////////////////////////////////////////////////////////////////// + +#include "Timers.h" + +using namespace arangodb::basics; + +std::vector Timers::starts(TIMER_MAX); +std::vector Timers::totals(TIMER_MAX); +std::vector Timers::counts(TIMER_MAX); + +void Timers::clear() { + for (auto& it : totals) { + it = 0.0; + } + for (auto& it : counts) { + it = 0; + } +} + +std::map> Timers::get() { + std::map> result; + + int const n = static_cast(TIMER_MAX); + for (int i = static_cast(TIMER_MIN) + 1; i < n; ++i) { + result.emplace(translateName(TimerType(i)), std::make_pair(totals[i], counts[i])); + } + return result; +} + +std::string Timers::translateName(TimerType type) { + switch (type) { + case JS_INSERT_ALL: + return "JS_INSERT_ALL"; + case JS_INSERT_V8_TO_VPACK: + return "JS_INSERT_V8_TO_VPACK"; + case JS_INSERT_VPACK_TO_V8: + return "JS_INSERT_VPACK_TO_V8"; + + default: + return "UNKNOWN"; + } +} + + diff --git a/lib/Basics/Timers.h b/lib/Basics/Timers.h new file mode 100644 index 0000000000..fa77457ea5 --- /dev/null +++ b/lib/Basics/Timers.h @@ -0,0 +1,69 @@ +//////////////////////////////////////////////////////////////////////////////// +/// DISCLAIMER +/// +/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LIB_BASICS_TIMERS_H +#define LIB_BASICS_TIMERS_H 1 + +#include "Basics/Common.h" + +#ifdef USE_TIMERS + +#define TIMER_START(name) arangodb::basics::Timers::starts[arangodb::basics::Timers::name] = TRI_microtime() +#define TIMER_STOP(name) arangodb::basics::Timers::totals[arangodb::basics::Timers::name] += TRI_microtime() - arangodb::basics::Timers::starts[arangodb::basics::Timers::name]; ++arangodb::basics::Timers::counts[arangodb::basics::Timers::name] + +#else + +#define TIMER_START(name) do { } while (false) +#define TIMER_STOP(name) do { } while (false) + +#endif + +namespace arangodb { +namespace basics { + +class Timers { + Timers() = delete; + + public: + enum TimerType : int { + TIMER_MIN = 0, + + JS_INSERT_ALL, + JS_INSERT_VPACK_TO_V8, + JS_INSERT_V8_TO_VPACK, + + TIMER_MAX + }; + + static void clear(); + static std::map> get(); + static std::string translateName(TimerType); + + static std::vector starts; + static std::vector totals; + static std::vector counts; +}; +} +} + +#endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e626daed94..308c97e8fc 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -177,6 +177,7 @@ add_library(${LIB_ARANGO} STATIC Basics/StringUtils.cpp Basics/Thread.cpp Basics/ThreadPool.cpp + Basics/Timers.cpp Basics/Utf8Helper.cpp Basics/VelocyPackHelper.cpp Basics/WorkMonitor.cpp