Version 1.34.2+ | Production Ready | Optimized for Large-Scale Applications
This comprehensive guide covers performance optimization techniques for the Supabase UE5 Plugin, ensuring your application can handle enterprise-level workloads efficiently and reliably.
The Supabase UE5 Plugin is engineered for high-performance scenarios with built-in optimizations:
// Efficient: Uses shared subsystem connection
UAsyncQuery* Query = UAsyncQuery::AsyncQuery(this, "users", "*", Filters);
// Less efficient: Creates new connection per operation
USupabaseConnection* DirectConnection = NewObject<USupabaseConnection>();
UAsyncQuery* Query = UAsyncQuery::AsyncQueryAdvanced(this, DirectConnection, "users", "*", Filters);
// Access performance metrics through subsystem
USupabaseSubsystem* Subsystem = USupabaseManager::GetSupabaseSubsystem(this);
if (Subsystem) {
FSupabaseHealthStatus Health = Subsystem->GetHealthStatus();
UE_LOG(LogTemp, Log, TEXT("Operations Per Second: %.2f"), Health.OperationsPerSecond);
UE_LOG(LogTemp, Log, TEXT("Memory Usage: %d MB"), Health.MemoryUsageMB);
UE_LOG(LogTemp, Log, TEXT("Active Connections: %d"), Health.ActiveConnections);
}
// Optimized: Only checks existence with LIMIT 1
UAsyncDoesRowExist* ExistCheck = UAsyncDoesRowExist::DoesRowExistAsync(this, "users", "123");
// Generates: SELECT id FROM users WHERE id='123' LIMIT 1
// Instead of: SELECT * FROM users WHERE id='123'
// Good: Select only needed fields
UAsyncQuery* Query = UAsyncQuery::AsyncQuery(this, "users", "id,email,created_at", Filters);
// Avoid: Selecting all fields when not needed
UAsyncQuery* Query = UAsyncQuery::AsyncQuery(this, "users", "*", Filters);
// Efficient batch processing with UPersistentMap
UPersistentMap* PersistentMap = UPersistentMap::CreatePersistentMap(this, "game_state");
PersistentMap->SetBatchSize(100); // Process 100 records at once
PersistentMap->SetAutoSave(true, 300.0f); // Auto-save every 5 minutes
PersistentMap->SaveActorsToSupabase(); // Batch save all actors
All async operations now feature automatic cleanup:
// Memory is automatically managed
UAsyncLogin* LoginTask = UAsyncLogin::LoginAsync(this, Email, Password);
LoginTask->OnSuccess.AddDynamic(this, &AMyActor::OnLoginSuccess);
// No manual cleanup needed - handled automatically in BeginDestroy()
// Efficient: Reuses subsystem connection
void PerformMultipleOperations() {
// All operations share the same connection through subsystem
UAsyncQuery::AsyncQuery(this, "users", "*", TArray<FQueryFilter>());
UAsyncInsertRow::InsertRowAsync(this, "logs", LogData);
UAsyncUpdateRow::UpdateRowAsync(this, "stats", RecordId, UpdateData);
}
// Monitor memory usage in production
void CheckMemoryUsage() {
USupabaseSubsystem* Subsystem = USupabaseManager::GetSupabaseSubsystem(this);
if (Subsystem) {
FSupabaseHealthStatus Health = Subsystem->GetHealthStatus();
if (Health.MemoryUsageMB > 100) { // Alert if over 100MB
UE_LOG(LogTemp, Warning, TEXT("High memory usage detected: %d MB"), Health.MemoryUsageMB);
}
}
}
// Configure performance settings during initialization
USupabaseConnection* Connection = NewObject<USupabaseConnection>();
Connection->SupabaseServerUrl = TEXT("https://your-project.supabase.co");
Connection->SupabaseCredentials.AnonymousKey = TEXT("your-anon-key");
// Performance settings
Connection->MaxConcurrentConnections = 10;
Connection->ConnectionTimeoutSeconds = 30.0f;
Connection->RetryAttempts = 3;
USupabaseManager::InitializeSupabase(this, Connection);
// Configure UPersistentMap for optimal performance
UPersistentMap* PersistentMap = UPersistentMap::CreatePersistentMap(this, "game_world");
// Performance configuration
FPersistentMapConfig Config;
Config.bBatchOperations = true;
Config.BatchSize = 50; // Optimal batch size for your use case
Config.bAutoSave = true;
Config.AutoSaveInterval = 300.0f; // 5-minute intervals
Config.bValidateData = false; // Disable in production for performance
Config.MaxRetries = 3;
Config.RetryDelay = 2.0f;
PersistentMap->SetConfiguration(Config);
// Configure UEntityPersistence for actors
UEntityPersistence* Persistence = Actor->FindComponentByClass<UEntityPersistence>();
FEntityPersistenceConfig Config;
Config.bAutoSave = true;
Config.AutoSaveInterval = 120.0f; // 2-minute auto-save
Config.bValidateData = false; // Disable validation in production
Config.bBatchWithOthers = true; // Enable batch processing
Config.MaxRetries = 2;
Persistence->SetConfiguration(Config);
The plugin monitors these key performance indicators:
struct FPerformanceMetrics {
double OperationsPerSecond; // Target: 100+ ops/sec
SIZE_T MemoryUsageMB; // Target: <50MB baseline
double AverageResponseTimeMS; // Target: <100ms average
double P95ResponseTimeMS; // Target: <500ms P95
int32 ConcurrentConnections; // Target: 10+ concurrent
int32 MaxBatchSize; // Target: 1000+ records
};
// Benchmark large dataset operations
void BenchmarkPerformance() {
const int32 RecordCount = 10000;
TArray<FString> TestData = GenerateTestData(RecordCount);
double StartTime = FPlatformTime::Seconds();
// Batch insert operation
UPersistentMap* PersistentMap = UPersistentMap::CreatePersistentMap(this, "benchmark_test");
for (const FString& Data : TestData) {
PersistentMap->SetValue("test_key_" + FString::FromInt(i), Data);
}
PersistentMap->SaveToSupabase(); // Batch save
double TotalTime = FPlatformTime::Seconds() - StartTime;
double RecordsPerSecond = RecordCount / TotalTime;
UE_LOG(LogTemp, Log, TEXT("Performance: %.2f records/second"), RecordsPerSecond);
}
// Efficient real-time subscriptions
UAsyncRealtime* Realtime = UAsyncRealtime::StartRealtimeAsync(this, "public", "users");
Realtime->OnInsert.AddDynamic(this, &AMyActor::OnUserInserted);
Realtime->OnUpdate.AddDynamic(this, &AMyActor::OnUserUpdated);
// Automatic cleanup ensures no memory leaks
// Use specific channels for different data types
UAsyncRealtime* UserRealtime = UAsyncRealtime::StartRealtimeAsync(this, "public", "users");
UAsyncRealtime* GameRealtime = UAsyncRealtime::StartRealtimeAsync(this, "public", "game_events");
// Channels are automatically managed by the subsystem
✅ DO:
❌ DON’T:
// Implement performance monitoring
void MonitorPerformance() {
USupabaseSubsystem* Subsystem = USupabaseManager::GetSupabaseSubsystem(this);
if (Subsystem) {
FSupabaseHealthStatus Health = Subsystem->GetHealthStatus();
// Log performance metrics
UE_LOG(LogSupabase, Log, TEXT("Performance Metrics:"));
UE_LOG(LogSupabase, Log, TEXT(" Operations/Sec: %.2f"), Health.OperationsPerSecond);
UE_LOG(LogSupabase, Log, TEXT(" Memory Usage: %d MB"), Health.MemoryUsageMB);
UE_LOG(LogSupabase, Log, TEXT(" Avg Response: %.2f ms"), Health.AverageResponseTimeMS);
UE_LOG(LogSupabase, Log, TEXT(" Active Connections: %d"), Health.ActiveConnections);
// Alert on performance issues
if (Health.AverageResponseTimeMS > 200.0) {
UE_LOG(LogSupabase, Warning, TEXT("High response times detected"));
}
if (Health.MemoryUsageMB > 100) {
UE_LOG(LogSupabase, Warning, TEXT("High memory usage detected"));
}
}
}
Issue: High Memory Usage
// Solution: Verify async operations are properly cleaned up
void CheckAsyncCleanup() {
// All async operations should automatically cleanup
// If memory keeps growing, check for:
// 1. Unreleased delegates
// 2. Retained references to completed operations
// 3. Large response data not being cleared
}
Issue: Slow Query Performance
// Solution: Optimize queries and use proper indexing
void OptimizeQueries() {
// 1. Use specific field selection
UAsyncQuery::AsyncQuery(this, "users", "id,email", Filters);
// 2. Add appropriate filters to reduce result sets
TArray<FQueryFilter> Filters;
FQueryFilter Filter;
Filter.Column = "active";
Filter.Operator = "eq";
Filter.Value = "true";
Filters.Add(Filter);
// 3. Consider database indexing on frequently queried columns
}
Issue: Connection Bottlenecks
// Solution: Use subsystem architecture properly
void EnsureProperConnectionUsage() {
// Correct: Uses shared subsystem connection
UAsyncQuery::AsyncQuery(this, "users", "*", Filters);
// Incorrect: Creates unnecessary direct connections
// USupabaseConnection* Connection = NewObject<USupabaseConnection>();
// UAsyncQuery::AsyncQueryAdvanced(this, Connection, "users", "*", Filters);
}
For performance-related questions and optimization tips:
This documentation is maintained for Supabase UE5 Plugin v1.34.2+. Performance characteristics may vary based on your specific use case, network conditions, and Supabase project configuration.