BehaviorTree.RecordFrameSearchTimes

BehaviorTree.RecordFrameSearchTimes

#Overview

name: BehaviorTree.RecordFrameSearchTimes

This variable is created as a Console Variable (cvar).

It is referenced in 5 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of BehaviorTree.RecordFrameSearchTimes is to enable performance monitoring for Behavior Tree search operations in Unreal Engine’s AI system. It is used to record and measure the execution time of Behavior Tree searches on a per-frame basis.

This setting variable is primarily used by the AI Module, specifically within the BehaviorTreeComponent. It is part of the performance profiling and debugging system for Behavior Trees.

The value of this variable is set through a console variable (CVarBTRecordFrameSearchTimes) which can be modified at runtime. By default, it is set to 0, meaning the feature is disabled.

This variable interacts closely with several other variables within the BehaviorTreeComponent:

Developers should be aware that:

  1. This feature is only available in non-shipping builds (#if !UE_BUILD_SHIPPING)
  2. Enabling this can have a small performance overhead due to the additional timing code
  3. The results are processed at the end of each frame in the EndFrame() function

Best practices when using this variable include:

  1. Use it primarily for debugging and performance optimization phases
  2. Remember to disable it in production builds to avoid any potential performance impact
  3. Analyze the output in conjunction with other profiling tools for a comprehensive performance picture

Regarding the associated variable CVarBTRecordFrameSearchTimes:

The purpose of CVarBTRecordFrameSearchTimes is to provide a runtime-configurable way to enable or disable the Behavior Tree search time recording feature. It is a console variable that controls the behavior of the BehaviorTree.RecordFrameSearchTimes setting.

This variable is used in the AI Module, specifically within the BehaviorTreeComponent, to determine whether to record search times.

The value of CVarBTRecordFrameSearchTimes is set when the console variable is created, with an initial value of 0 (disabled). It can be changed at runtime through console commands.

It interacts directly with the timing code in the BehaviorTreeComponent, controlling whether the timing operations are performed.

Developers should be aware that:

  1. Changes to this variable take effect immediately, allowing for on-the-fly profiling
  2. Setting it to a non-zero value enables timing, while 0 disables it

Best practices for using CVarBTRecordFrameSearchTimes include:

  1. Use it in development and testing environments for performance analysis
  2. Be cautious about enabling it in performance-critical scenarios, as it adds some overhead
  3. Consider creating a user-friendly way to toggle this setting for easier debugging in development builds

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/AIModule/Private/BehaviorTree/BehaviorTreeComponent.cpp:26

Scope: file

Source code excerpt:


// Code for timing BT Search
static TAutoConsoleVariable<int32> CVarBTRecordFrameSearchTimes(TEXT("BehaviorTree.RecordFrameSearchTimes"), 0, TEXT("Record Search Times Per Frame For Perf Stats"));
#if !UE_BUILD_SHIPPING
bool UBehaviorTreeComponent::bAddedEndFrameCallback = false;
double UBehaviorTreeComponent::FrameSearchTime = 0.;
int32 UBehaviorTreeComponent::NumSearchTimeCalls = 0;
#endif

#Associated Variable and Callsites

This variable is associated with another variable named CVarBTRecordFrameSearchTimes. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Runtime/AIModule/Private/BehaviorTree/BehaviorTreeComponent.cpp:26

Scope: file

Source code excerpt:


// Code for timing BT Search
static TAutoConsoleVariable<int32> CVarBTRecordFrameSearchTimes(TEXT("BehaviorTree.RecordFrameSearchTimes"), 0, TEXT("Record Search Times Per Frame For Perf Stats"));
#if !UE_BUILD_SHIPPING
bool UBehaviorTreeComponent::bAddedEndFrameCallback = false;
double UBehaviorTreeComponent::FrameSearchTime = 0.;
int32 UBehaviorTreeComponent::NumSearchTimeCalls = 0;
#endif

#Loc: <Workspace>/Engine/Source/Runtime/AIModule/Private/BehaviorTree/BehaviorTreeComponent.cpp:1142

Scope (from outer to inner):

file
function     void UBehaviorTreeComponent::RequestExecution

Source code excerpt:

	CSV_SCOPED_TIMING_STAT_EXCLUSIVE(BehaviorTreeSearch);

	FScopedSwitchedCountedDurationTimer ScopedSwitchedCountedDurationTimer(FrameSearchTime, NumSearchTimeCalls, CVarBTRecordFrameSearchTimes.GetValueOnGameThread() != 0);
#endif

	UE_VLOG(GetOwner(), LogBehaviorTree, Log, TEXT("Execution request by %s (result: %s)"),
		*UBehaviorTreeTypes::DescribeNodeHelper(RequestedBy),
		*UBehaviorTreeTypes::DescribeNodeResult(ContinueWithResult));

#Loc: <Workspace>/Engine/Source/Runtime/AIModule/Private/BehaviorTree/BehaviorTreeComponent.cpp:1976

Scope (from outer to inner):

file
function     void UBehaviorTreeComponent::ProcessExecutionRequest

Source code excerpt:

		CSV_SCOPED_TIMING_STAT_EXCLUSIVE(BehaviorTreeSearch);

		FScopedSwitchedCountedDurationTimer ScopedSwitchedCountedDurationTimer(FrameSearchTime, NumSearchTimeCalls, CVarBTRecordFrameSearchTimes.GetValueOnGameThread() != 0);
#endif

		// copy current memory in case we need to rollback search
		CopyInstanceMemoryToPersistent();

		// deactivate up to ExecuteNode

#Loc: <Workspace>/Engine/Source/Runtime/AIModule/Private/BehaviorTree/BehaviorTreeComponent.cpp:3516

Scope (from outer to inner):

file
function     void UBehaviorTreeComponent::EndFrame

Source code excerpt:

void UBehaviorTreeComponent::EndFrame()
{
	if (CVarBTRecordFrameSearchTimes.GetValueOnGameThread() != 0)
	{
		const double FrameSearchTimeMilliSecsDouble = FrameSearchTime * 1000.;
		const double AvFrameSearchTimeMilliSecsDouble = (NumSearchTimeCalls > 0) ? FrameSearchTimeMilliSecsDouble / static_cast<double>(NumSearchTimeCalls) : 0.;
		const float FrameSearchTimeMilliSecsFloat = static_cast<float>(FrameSearchTimeMilliSecsDouble);
		const float NumSearchTimeCallsFloat = static_cast<float>(NumSearchTimeCalls);
		const float AvFrameSearchTimeMilliSecsFloat = static_cast<float>(AvFrameSearchTimeMilliSecsDouble);