diff --git a/cmake_templates/zeek-config.h.in b/cmake_templates/zeek-config.h.in index 81409c8a09..67ab0a5b8e 100644 --- a/cmake_templates/zeek-config.h.in +++ b/cmake_templates/zeek-config.h.in @@ -241,6 +241,9 @@ /* Spicy analyzers built in. */ #cmakedefine01 USE_SPICY_ANALYZERS +/* Enable/disable ZAM profiling capability */ +#cmakedefine ENABLE_ZAM_PROFILE + /* String with host architecture (e.g., "linux-x86_64") */ #define HOST_ARCHITECTURE "@HOST_ARCHITECTURE@" diff --git a/configure b/configure index 7d91aedc8a..34cc68bfc6 100755 --- a/configure +++ b/configure @@ -65,6 +65,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]... --enable-static-binpac build binpac statically (ignored if --with-binpac is specified) --enable-static-broker build Broker statically (ignored if --with-broker is specified) --enable-werror build with -Werror + --enable-ZAM-profiling build with ZAM profiling enabled (--enable-debug implies this) --disable-af-packet don't include native AF_PACKET support (Linux only) --disable-archiver don't build or install zeek-archiver tool --disable-auxtools don't build or install auxiliary tools @@ -254,9 +255,11 @@ while [ $# -ne 0 ]; do --enable-coverage) append_cache_entry ENABLE_COVERAGE BOOL true append_cache_entry ENABLE_DEBUG BOOL true + append_cache_entry ENABLE_ZAM_PROFILE BOOL true ;; --enable-debug) append_cache_entry ENABLE_DEBUG BOOL true + append_cache_entry ENABLE_ZAM_PROFILE BOOL true ;; --enable-fuzzers) append_cache_entry ZEEK_ENABLE_FUZZERS BOOL true @@ -280,6 +283,9 @@ while [ $# -ne 0 ]; do --enable-werror) append_cache_entry BUILD_WITH_WERROR BOOL true ;; + --enable-ZAM-profiling) + append_cache_entry ENABLE_ZAM_PROFILE BOOL true + ;; --disable-af-packet) append_cache_entry DISABLE_AF_PACKET BOOL true ;; diff --git a/src/Options.cc b/src/Options.cc index 41c7bfbfde..0c15fbe074 100644 --- a/src/Options.cc +++ b/src/Options.cc @@ -192,7 +192,7 @@ static void print_analysis_help() { fprintf(stderr, " no-ZAM-opt omit low-level ZAM optimization\n"); fprintf(stderr, " optimize-all optimize all scripts, even inlined ones\n"); fprintf(stderr, " optimize-AST optimize the (transformed) AST; implies xform\n"); - fprintf(stderr, " profile-ZAM generate to stdout a ZAM execution profile; implies -O ZAM\n"); + fprintf(stderr, " profile-ZAM generate to zprof.out a ZAM execution profile; implies -O ZAM\n"); fprintf(stderr, " report-recursive report on recursive functions and exit\n"); fprintf(stderr, " xform transform scripts to \"reduced\" form\n"); @@ -245,7 +245,7 @@ static void set_analysis_option(const char* opt, Options& opts) { else if ( util::streq(opt, "optimize-AST") ) a_o.activate = a_o.optimize_AST = true; else if ( util::streq(opt, "profile-ZAM") ) - a_o.activate = a_o.gen_ZAM_code = a_o.profile_ZAM = true; + a_o.activate = a_o.profile_ZAM = true; else if ( util::streq(opt, "report-C++") ) a_o.report_CPP = true; else if ( util::streq(opt, "report-recursive") ) diff --git a/src/Var.cc b/src/Var.cc index db83f4e74b..e17e2dc15a 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -20,6 +20,7 @@ #include "zeek/Val.h" #include "zeek/module_util.h" #include "zeek/script_opt/IDOptInfo.h" +#include "zeek/script_opt/ScriptOpt.h" #include "zeek/script_opt/StmtOptInfo.h" #include "zeek/script_opt/UsageAnalyzer.h" @@ -399,7 +400,10 @@ void add_type(ID* id, TypePtr t, std::unique_ptr> attr) { static std::set all_module_names; -void add_module(const char* module_name) { all_module_names.emplace(module_name); } +void add_module(const char* module_name) { + all_module_names.emplace(module_name); + switch_to_module(module_name); +} const std::set& module_names() { return all_module_names; } diff --git a/src/script_opt/ScriptOpt.cc b/src/script_opt/ScriptOpt.cc index d9051f8113..1dcf500d54 100644 --- a/src/script_opt/ScriptOpt.cc +++ b/src/script_opt/ScriptOpt.cc @@ -17,6 +17,7 @@ #include "zeek/script_opt/UsageAnalyzer.h" #include "zeek/script_opt/UseDefs.h" #include "zeek/script_opt/ZAM/Compile.h" +#include "zeek/script_opt/ZAM/Profile.h" namespace zeek::detail { @@ -310,6 +311,22 @@ static void init_options() { add_file_analysis_pattern(analysis_options, zo); } + if ( analysis_options.profile_ZAM ) { + auto zsamp = getenv("ZEEK_ZAM_PROF_SAMPLING_RATE"); + if ( zsamp ) { + analysis_options.profile_sampling_rate = atoi(zsamp); + if ( analysis_options.profile_sampling_rate == 0 ) { + fprintf(stderr, "bad ZAM sampling profile rate from $ZEEK_ZAM_PROF_SAMPLING_RATE: %s\n", zsamp); + analysis_options.profile_ZAM = false; + } + } + + // If no ZAM generation options have been specified, default to + // the usual "-O ZAM" profile. But if they have, honor those. + if ( ! analysis_options.gen_ZAM_code ) + analysis_options.gen_ZAM = true; + } + if ( analysis_options.gen_ZAM ) { analysis_options.gen_ZAM_code = true; analysis_options.inliner = true; @@ -437,6 +454,19 @@ static void analyze_scripts_for_ZAM() { auto pfs = std::make_shared(funcs, nullptr, true); + if ( analysis_options.profile_ZAM ) { +#ifdef ENABLE_ZAM_PROFILE + blocks = std::make_unique(funcs); + const auto prof_filename = "zprof.out"; + analysis_options.profile_file = fopen(prof_filename, "w"); + if ( ! analysis_options.profile_file ) + reporter->FatalError("cannot create ZAM profiling log %s", prof_filename); +#else + fprintf(stderr, "warning: zeek was not built with --enable-ZAM-profiling\n"); + analysis_options.profile_ZAM = false; +#endif + } + bool report_recursive = analysis_options.report_recursive; std::unique_ptr inl; if ( analysis_options.inliner ) @@ -599,10 +629,19 @@ void profile_script_execution() { if ( analysis_options.profile_ZAM ) { report_ZOP_profile(); + ProfMap module_prof; + for ( auto& f : funcs ) { - if ( f.Body()->Tag() == STMT_ZAM ) - cast_intrusive(f.Body())->ProfileExecution(); + if ( f.Body()->Tag() == STMT_ZAM ) { + auto zb = cast_intrusive(f.Body()); + zb->ProfileExecution(module_prof); + } } + + for ( auto& mp : module_prof ) + if ( mp.second.first > 0 ) + fprintf(analysis_options.profile_file, "module %s sampled CPU time %.06f, %d sampled instructions\n", + mp.first.c_str(), mp.second.second, static_cast(mp.second.first)); } } diff --git a/src/script_opt/ScriptOpt.h b/src/script_opt/ScriptOpt.h index 715f7d9dc4..76126a1fe5 100644 --- a/src/script_opt/ScriptOpt.h +++ b/src/script_opt/ScriptOpt.h @@ -75,6 +75,12 @@ struct AnalyOpt { // Produce a profile of ZAM execution. bool profile_ZAM = false; + // ZAM profiling sampling rate. Set via ZEEK_ZAM_PROF_SAMPLING_RATE. + int profile_sampling_rate = 100; + + // An associated file to which to write the profile. + FILE* profile_file = nullptr; + // If true, dump out transformed code: the results of reducing // interpreted scripts, and, if optimize is set, of then optimizing // them. @@ -217,6 +223,10 @@ extern void analyze_global_stmts(Stmt* stmts); // Returns the body and scope for the previously analyzed global statements. extern std::pair get_global_stmts(); +// Informs script optimization that parsing is switching to the given module. +// Used to associate module names with profiling information. +extern void switch_to_module(const char* module); + // Add a pattern to the "only_funcs" list. extern void add_func_analysis_pattern(AnalyOpt& opts, const char* pat);