Add option to enable Google Profiler.
Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/540c09e6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/540c09e6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/540c09e6 Branch: refs/heads/adaptive-bloom-filters Commit: 540c09e623744c5ebf24f845372baaddca4265d1 Parents: 8230b12 Author: Navneet Potti <nav...@apache.org> Authored: Mon Jun 13 15:17:06 2016 -0500 Committer: Zuyu Zhang <zu...@apache.org> Committed: Mon Jun 13 14:57:16 2016 -0700 ---------------------------------------------------------------------- CMakeLists.txt | 26 ++++++++++++++++++++++++++ cli/CMakeLists.txt | 6 +++++- cli/CliConfig.h.in | 1 + cli/QuickstepCli.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 78 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/540c09e6/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e445f0..20e1fb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,6 +159,32 @@ else() ) endif() +# Include Google Perftools CPU Profiler. You probably want to +# use this option with CMAKE_BUILD_TYPE=RelWithDebInfo. +# Pass profiler_file_name to quickstep_cli_shell to actually +# run the profiler. The profiler only starts collecting +# samples after the first query, so that it runs against a +# warm buffer pool and caches. If you want to profile everything, +# including the first query run, set the environment variable +# CPUPROFILE instead of passing the flag profile_file_name +# Use google-pprof on the output file to convert it into a useful +# format like graphviz (dot). +option(ENABLE_GOOGLE_PROFILER "Include Google Perftools CPU Profiler." OFF) + +if (ENABLE_GOOGLE_PROFILER) + set_property( + DIRECTORY + APPEND PROPERTY COMPILE_DEFINITIONS QUICKSTEP_ENABLE_PROFILER + ) + + # TODO(navsan) Add a FindGperftools.cmake module and use that here. + check_include_files("gperftools/profiler.h" HAVE_GPERFTOOLS_PROFILER) + if (NOT HAVE_GPERFTOOLS_PROFILER) + message(FATAL_ERROR "Could not find gperftools. Ensure that it is installed.") + endif() + set(LIBS ${LIBS} profiler) +endif() + # Link against the system's threading library. find_package(Threads REQUIRED) set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT}) http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/540c09e6/cli/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index faf5040..44ec223 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -36,6 +36,10 @@ else() set(GFLAGS_LIB_NAME gflags_nothreads-static) endif() +if (ENABLE_GOOGLE_PROFILER) + set(QUICKSTEP_ENABLE_GOOGLE_PROFILER TRUE) +endif() + configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/CliConfig.h.in" "${CMAKE_CURRENT_BINARY_DIR}/CliConfig.h" @@ -106,7 +110,7 @@ target_link_libraries(quickstep_cli_DefaultsConfigurator if(QUICKSTEP_HAVE_LIBNUMA) target_link_libraries(quickstep_cli_DefaultsConfigurator ${LIBNUMA_LIBRARY}) -endif() +endif() target_link_libraries(quickstep_cli_InputParserUtil glog quickstep_utility_Macros http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/540c09e6/cli/CliConfig.h.in ---------------------------------------------------------------------- diff --git a/cli/CliConfig.h.in b/cli/CliConfig.h.in index b44dfb7..69f4d8a 100644 --- a/cli/CliConfig.h.in +++ b/cli/CliConfig.h.in @@ -17,3 +17,4 @@ #cmakedefine QUICKSTEP_USE_LINENOISE #cmakedefine QUICKSTEP_OS_WINDOWS +#cmakedefine QUICKSTEP_ENABLE_GOOGLE_PROFILER http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/540c09e6/cli/QuickstepCli.cpp ---------------------------------------------------------------------- diff --git a/cli/QuickstepCli.cpp b/cli/QuickstepCli.cpp index fbe7e3b..0b64fda 100644 --- a/cli/QuickstepCli.cpp +++ b/cli/QuickstepCli.cpp @@ -36,7 +36,7 @@ #include <stdlib.h> #endif -#include "cli/CliConfig.h" // For QUICKSTEP_USE_LINENOISE. +#include "cli/CliConfig.h" // For QUICKSTEP_USE_LINENOISE, QUICKSTEP_ENABLE_GOOGLE_PROFILER. #include "cli/CommandExecutor.hpp" #include "cli/DropRelation.hpp" @@ -48,6 +48,10 @@ typedef quickstep::LineReaderLineNoise LineReaderImpl; typedef quickstep::LineReaderDumb LineReaderImpl; #endif +#ifdef QUICKSTEP_ENABLE_GOOGLE_PROFILER +#include <gperftools/profiler.h> +#endif + #include "cli/DefaultsConfigurator.hpp" #include "cli/InputParserUtil.hpp" #include "cli/PrintToScreen.hpp" @@ -157,6 +161,30 @@ DEFINE_bool(initialize_db, false, "If true, initialize a database."); DEFINE_bool(print_query, false, "Print each input query statement. This is useful when running a " "large number of queries in a batch."); +DEFINE_string(profile_file_name, "", + "If nonempty, enable profiling using GOOGLE CPU Profiler, and write " + "its output to the given file name. This flag has no effect if " + "ENABLE_GOOGLE_PROFILER CMake flag was not set during build. " + "The profiler only starts collecting samples after the first query, " + "so that it runs against a warm buffer pool and caches. If you want to profile " + "everything, including the first query run, set the " + "environment variable CPUPROFILE instead of passing this flag."); + // Here's a detailed explanation of why we skip the first query run + // during profiling: + // Unless youâve preloaded the buffer pool (which is not always a good + // idea), the first run of the query results in disk I/O and other overhead + // that significantly skews the profiling results. Itâs the same reason we donât + // include the first run time in our benchmarking: when profiling query + // execution, it makes more sense to get numbers using a warm buffer pool and + // warm caches. This is not *always* the right thing to do: itâs obviously + // wrong for profiling the TextScan operator. In those cases, you might want + // to put in your own Profiler probes (just follow the start/stop pattern used + // in this file) or just run quickstep with the CPUPROFILE environment variable + // set (as per gperftools documentation) to get the full profile for the + // entire execution. + // To put things in perspective, the first run is, in my experiments, about 5-10 + // times more expensive than the average run. That means the query needs to be + // run at least a hundred times to make the impact of the first run small (< 5 %). } // namespace quickstep @@ -345,6 +373,9 @@ int main(int argc, char* argv[]) { std::unique_ptr<SqlParserWrapper> parser_wrapper(new SqlParserWrapper()); std::chrono::time_point<std::chrono::steady_clock> start, end; +#ifdef QUICKSTEP_ENABLE_GOOGLE_PROFILER + bool started_profiling = false; +#endif for (;;) { string *command_string = new string(); *command_string = line_reader.getNextCommand(); @@ -446,6 +477,13 @@ int main(int argc, char* argv[]) { reset_parser = true; break; } +#ifdef QUICKSTEP_ENABLE_GOOGLE_PROFILER + // Profile only if profile_file_name flag is set + if (!started_profiling && !quickstep::FLAGS_profile_file_name.empty()) { + started_profiling = true; + ProfilerStart(quickstep::FLAGS_profile_file_name.c_str()); + } +#endif } if (quitting) { @@ -456,6 +494,13 @@ int main(int argc, char* argv[]) { } } +#ifdef QUICKSTEP_ENABLE_GOOGLE_PROFILER + if (started_profiling) { + ProfilerStop(); + ProfilerFlush(); + } +#endif + // Kill the foreman and workers. QueryExecutionUtil::BroadcastPoisonMessage(main_thread_client_id, &bus);