SynthBenchmark
SynthBenchmark
#Overview
name: SynthBenchmark
This variable is created as a Console Variable (cvar).
- type:
Cmd
- help:
Run simple benchmark to get some metrics to find reasonable game settings automatically\nOptional (float) parameter allows to scale with work amount to trade time or precision (default: 10).
It is referenced in 9
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of SynthBenchmark is to provide a synthetic benchmarking tool for measuring the performance of CPU and GPU in Unreal Engine. It is used to gather metrics that help in automatically finding reasonable game settings and for hardware surveys.
SynthBenchmark is primarily used by the Engine, ApplicationCore, and HardwareSurvey modules. It’s part of the core functionality that helps in performance analysis and hardware profiling across different platforms (Windows, Mac, Unix).
The value of this variable is set through the Run() method of the ISynthBenchmark interface. This method is called in various platform-specific survey implementations (Windows, Mac, Unix) and in the Scalability namespace for benchmarking quality levels.
SynthBenchmark interacts with several other variables and systems:
- It’s used in conjunction with FQualityLevels for determining appropriate graphics settings.
- It’s part of the FSurveyResults struct, which is used for hardware surveys.
- It interacts with analytics systems to report hardware stats.
Developers should be aware of the following when using SynthBenchmark:
- It’s a cross-platform tool, but implementation details may vary slightly between platforms.
- The benchmarking process can be time-consuming, so it should be used judiciously.
- Results are used for both immediate performance adjustments and long-term analytics.
Best practices when using SynthBenchmark include:
- Use it during initial setup or when major hardware changes are detected, not frequently during gameplay.
- Consider the WorkScale parameter when calling Run() to balance between precision and time taken.
- Be cautious about using the results in shipping builds, as indicated by the presence of the UE_BUILD_SHIPPING check in the code.
- Use the computed performance indices (CPUPerfIndex and GPUPerfIndex) rather than raw benchmark results for decision-making in your game logic.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/GameEngine.cpp:183
Scope: file
Source code excerpt:
static FAutoConsoleCommand GSynthBenchmarkCmd(
TEXT("SynthBenchmark"),
TEXT("Run simple benchmark to get some metrics to find reasonable game settings automatically\n")
TEXT("Optional (float) parameter allows to scale with work amount to trade time or precision (default: 10)."),
FConsoleCommandWithArgsDelegate::CreateStatic(&RunSynthBenchmark)
);
EWindowMode::Type GetWindowModeType(EWindowMode::Type WindowMode)
#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Mac/MacPlatformSurvey.cpp:57
Scope (from outer to inner):
file
function bool FMacPlatformSurvey::GetSurveyResults
Source code excerpt:
}
ISynthBenchmark::Get().Run(OutResults.SynthBenchmark, true, 5.f);
FString RHIName;
ISynthBenchmark::Get().GetRHIInfo(OutResults.RHIAdapter, RHIName);
WriteFStringToResults(OutResults.RenderingAPI, RHIName);
// Get CPU speed
#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Unix/UnixPlatformSurvey.cpp:31
Scope (from outer to inner):
file
function bool FUnixPlatformSurvey::GetSurveyResults
Source code excerpt:
// Synth benchmark
ISynthBenchmark::Get().Run(OutResults.SynthBenchmark, true, 5.f);
OutResults.ErrorCount++;
WriteFStringToResults(OutResults.LastSurveyError, TEXT("Survey is incomplete"));
WriteFStringToResults(OutResults.LastSurveyErrorDetail, TEXT("CPU, OS details are missing"));
return true;
#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Windows/WindowsPlatformSurvey.cpp:84
Scope (from outer to inner):
file
function bool FWindowsPlatformSurvey::GetSurveyResults
Source code excerpt:
OutResults.CPUCount = SystemInfo.dwNumberOfProcessors;
ISynthBenchmark::Get().Run(OutResults.SynthBenchmark, true, 5.f);
FString RHIName;
ISynthBenchmark::Get().GetRHIInfo(OutResults.RHIAdapter, RHIName);
WriteFStringToResults(OutResults.RenderingAPI, RHIName);
// Get CPU speed
#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Public/GenericPlatform/GenericPlatformSurvey.h:217
Scope: file
Source code excerpt:
TCHAR LastPerformanceIndexErrorDetail[MaxStringLength];
FSynthBenchmarkResults SynthBenchmark;
};
/**
* Generic implementation for most platforms, these tend to be unused and unimplemented
**/
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Scalability.cpp:682
Scope (from outer to inner):
file
namespace Scalability
function FQualityLevels BenchmarkQualityLevels
Source code excerpt:
FQualityLevels Results;
FSynthBenchmarkResults SynthBenchmark;
ISynthBenchmark::Get().Run(SynthBenchmark, true, WorkScale);
float CPUPerfIndex = SynthBenchmark.ComputeCPUPerfIndex(/*out*/ &Results.CPUBenchmarkSteps) * CPUMultiplier;
float GPUPerfIndex = SynthBenchmark.ComputeGPUPerfIndex(/*out*/ &Results.GPUBenchmarkSteps) * GPUMultiplier;
#if !UE_BUILD_SHIPPING
if (CVarTestCPUPerfIndexOverride.GetValueOnAnyThread() > 0.0f)
{
CPUPerfIndex = CVarTestCPUPerfIndexOverride.GetValueOnAnyThread();
}
#Loc: <Workspace>/Engine/Source/Runtime/HardwareSurvey/Private/HardwareSurveyModule.cpp:347
Scope (from outer to inner):
file
function void OnHardwareSurveyComplete
Source code excerpt:
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("IsLaptop"), SurveyResults.bIsLaptopComputer ? TEXT("true") : TEXT("false")));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("IsRemoteSession"), SurveyResults.bIsRemoteSession ? TEXT("true") : TEXT("false")));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.CPU0"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.CPUStats[0].ComputePerfIndex())));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.CPU1"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.CPUStats[1].ComputePerfIndex())));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.GPU0"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.GPUStats[0].ComputePerfIndex())));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.GPU1"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.GPUStats[1].ComputePerfIndex())));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.GPU2"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.GPUStats[2].ComputePerfIndex())));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.GPU3"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.GPUStats[3].ComputePerfIndex())));
HardwareStatsAttribs.Add(FAnalyticsEventAttribute(TEXT("SynthIdx.GPU4"), FString::Printf(TEXT("%.1f"), SurveyResults.SynthBenchmark.GPUStats[4].ComputePerfIndex())));
Analytics->RecordEvent(TEXT("HardwareStats.1"), HardwareStatsAttribs);
TArray<FAnalyticsEventAttribute> HardwareStatErrorsAttribs;
HardwareStatErrorsAttribs.Add(FAnalyticsEventAttribute(TEXT("ErrorCount"), FString::Printf(TEXT("%d"), SurveyResults.ErrorCount)));
HardwareStatErrorsAttribs.Add(FAnalyticsEventAttribute(TEXT("LastError"), SurveyResults.LastSurveyError));
#Loc: <Workspace>/Engine/Source/Runtime/SynthBenchmark/Private/SynthBenchmarkPrivate.cpp:27
Scope: file
Source code excerpt:
};
IMPLEMENT_MODULE( FSynthBenchmark, SynthBenchmark )
void FSynthBenchmark::StartupModule()
{
// This code will execute after your module is loaded into memory (but after global variables are initialized, of course.)
}
#Loc: <Workspace>/Engine/Source/Runtime/SynthBenchmark/Public/SynthBenchmark.h:20
Scope (from outer to inner):
file
class class ISynthBenchmark : public IModuleInterface
Source code excerpt:
virtual void Run(FSynthBenchmarkResults& Out, bool bGPUBenchmark = true, float WorkScale = 10.0f) const = 0;
// could be moved out of SynthBenchmark, it only requires the RHI, only returns valid data after the RHI started up
virtual void GetRHIDisplay(FGPUAdpater& Out) const = 0;
virtual void GetRHIInfo(FGPUAdpater& Out, FString& RHIName) const = 0;
/**
* Singleton-like access to this module's interface. This is just for convenience!
* Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.