#include "framework/ips_option.h"
#include "framework/module.h"
#include "main/snort_config.h"
-#include "profiler/memory_profiler_defs.h"
+#include "profiler/profiler_defs.h"
#include "protocols/packet.h"
// must appear after snort_config.h to avoid broken c++ map include
MemoryContext::MemoryContext(MemoryTracker&) { }
MemoryContext::~MemoryContext() = default;
+
+bool TimeProfilerStats::enabled = false;
}
extern const BaseApi* ips_regex;
{
public:
ProfilerModule() : Module("profiler", profiler_help, profiler_params) { }
+
bool set(const char*, Value&, SnortConfig*) override;
+ bool end(const char*, int, SnortConfig*) override;
Usage get_usage() const override
{ return GLOBAL; }
return false;
}
+bool ProfilerModule::end(const char*, int, SnortConfig* sc)
+{
+ TimeProfilerStats::set_enabled(sc->profiler->time.show);
+ return true;
+}
+
//-------------------------------------------------------------------------
// classification module
//-------------------------------------------------------------------------
//------------------------------------------------------
ProfilerConfig* profiler = nullptr;
-
LatencyConfig* latency = nullptr;
unsigned remote_control_port = 0;
#define s_time_table_title "module profile"
+// enabled is not in SnortConfig to avoid that ugly dependency
+// enabled is not in TimeContext because declaring it SO_PUBLIC made TimeContext visible
+// putting enabled in TimeProfilerStats seems to be the best solution
+bool TimeProfilerStats::enabled = false;
+
namespace time_stats
{
}
}
+TEST_CASE( "time profiler time context disabled", "[profiler][time_profiler]" )
+{
+ TimeProfilerStats stats;
+ REQUIRE_FALSE( stats );
+ TimeProfilerStats::set_enabled(false);
+
+ SECTION( "lifetime" )
+ {
+ {
+ TimeContext ctx(stats);
+ CHECK( ctx.active() );
+ CHECK( stats.ref_count == 0 );
+ }
+
+ CHECK( stats.ref_count == 0 );
+ }
+
+ SECTION( "manually managed lifetime" )
+ {
+ {
+ TimeContext ctx(stats);
+ CHECK( ctx.active() );
+ CHECK( stats.ref_count == 0 );
+ ctx.stop();
+ CHECK( ctx.active() );
+ CHECK( stats.ref_count == 0 );
+ }
+
+ CHECK( stats.ref_count == 0 );
+ }
+
+ SECTION( "updates stats" )
+ {
+ TimeContext ctx(stats);
+ avoid_optimization();
+ ctx.stop();
+
+ CHECK( !stats );
+ }
+
+ SECTION( "reentrance" )
+ {
+ {
+ TimeContext ctx1(stats);
+
+ CHECK( stats.ref_count == 0 );
+
+ {
+ TimeContext ctx2(stats);
+
+ CHECK( (stats.ref_count == 0) );
+ }
+
+ CHECK( stats.ref_count == 0 );
+ }
+
+ CHECK( stats.ref_count == 0 ); // ref_count restored
+ CHECK( stats.checks == 0 ); // only updated once
+ }
+}
+
TEST_CASE( "time profiler time context", "[profiler][time_profiler]" )
{
TimeProfilerStats stats;
REQUIRE_FALSE( stats );
+ TimeProfilerStats::set_enabled(true);
SECTION( "lifetime" )
{
hr_duration elapsed;
uint64_t checks;
mutable unsigned int ref_count;
+ static bool enabled;
+
+ static void set_enabled(bool b)
+ { enabled = b; }
+
+ static bool is_enabled()
+ { return enabled; }
void update(hr_duration delta)
{ elapsed += delta; ++checks; }
TimeContext(TimeProfilerStats& stats) :
stats(stats)
{
- if ( stats.enter() )
+ if ( stats.is_enabled() and stats.enter() )
sw.start();
}
~TimeContext()
- { stop(); }
+ {
+ if ( stats.is_enabled() )
+ stop();
+ }
// Use this for finer grained control of the TimeContext "lifetime"
void stop()
{
- if ( stopped_once )
+ if ( !stats.is_enabled() or stopped_once )
return; // stop() should only be executed once per context
stopped_once = true;
~TimeExclude()
{
+ if ( !TimeProfilerStats::is_enabled() )
+ return;
ctx.stop();
stats.elapsed -= tmp.elapsed;
}