v1.2.7 - Add configurable SQLite mmap_size (256MB) and cache_size (64MB) PRAGMAs for ~20% CPU reduction from DB read overhead

This commit is contained in:
Your Name
2026-02-23 09:48:01 -04:00
parent e94b1a81e3
commit 0dc5b75d7c
5 changed files with 67 additions and 5 deletions
+1 -1
View File
@@ -1 +1 @@
1946657 1950899
+22 -2
View File
@@ -951,6 +951,22 @@ static int validate_config_field(const char* key, const char* value, char* error
} }
return 0; return 0;
} }
// SQLite performance tuning
if (strcmp(key, "sqlite_mmap_size") == 0) {
if (!is_valid_positive_integer(value) && strcmp(value, "0") != 0) {
snprintf(error_msg, error_size, "invalid sqlite_mmap_size '%s' (must be non-negative integer bytes)", value);
return -1;
}
return 0;
}
if (strcmp(key, "sqlite_cache_size_kb") == 0) {
if (!is_valid_positive_integer(value)) {
snprintf(error_msg, error_size, "invalid sqlite_cache_size_kb '%s' (must be positive integer KB)", value);
return -1;
}
return 0;
}
// Boolean fields // Boolean fields
if (strcmp(key, "auth_enabled") == 0 || if (strcmp(key, "auth_enabled") == 0 ||
@@ -1719,7 +1735,9 @@ int populate_default_config_values(void) {
strcmp(key, "default_limit") == 0 || strcmp(key, "default_limit") == 0 ||
strcmp(key, "max_limit") == 0 || strcmp(key, "max_limit") == 0 ||
strcmp(key, "nip42_challenge_expiration") == 0 || strcmp(key, "nip42_challenge_expiration") == 0 ||
strcmp(key, "nip40_expiration_grace_period") == 0) { strcmp(key, "nip40_expiration_grace_period") == 0 ||
strcmp(key, "sqlite_mmap_size") == 0 ||
strcmp(key, "sqlite_cache_size_kb") == 0) {
data_type = "integer"; data_type = "integer";
} else if (strcmp(key, "auth_enabled") == 0 || } else if (strcmp(key, "auth_enabled") == 0 ||
strcmp(key, "nip40_expiration_enabled") == 0 || strcmp(key, "nip40_expiration_enabled") == 0 ||
@@ -4499,7 +4517,9 @@ int populate_all_config_values_atomic(const char* admin_pubkey, const char* rela
strcmp(key, "default_limit") == 0 || strcmp(key, "default_limit") == 0 ||
strcmp(key, "max_limit") == 0 || strcmp(key, "max_limit") == 0 ||
strcmp(key, "nip42_challenge_expiration") == 0 || strcmp(key, "nip42_challenge_expiration") == 0 ||
strcmp(key, "nip40_expiration_grace_period") == 0) { strcmp(key, "nip40_expiration_grace_period") == 0 ||
strcmp(key, "sqlite_mmap_size") == 0 ||
strcmp(key, "sqlite_cache_size_kb") == 0) {
data_type = "integer"; data_type = "integer";
} else if (strcmp(key, "auth_enabled") == 0 || } else if (strcmp(key, "auth_enabled") == 0 ||
strcmp(key, "nip40_expiration_enabled") == 0 || strcmp(key, "nip40_expiration_enabled") == 0 ||
+8
View File
@@ -83,6 +83,14 @@ static const struct {
// IP-based rate limiting or access control (which would require firewall protection anyway) // IP-based rate limiting or access control (which would require firewall protection anyway)
{"trust_proxy_headers", "true"}, {"trust_proxy_headers", "true"},
// SQLite Performance Tuning
// mmap_size: bytes of database file to memory-map (0 = disabled, 268435456 = 256MB recommended)
// Eliminates pread64 syscall overhead for database reads — significant CPU savings under load
{"sqlite_mmap_size", "268435456"},
// cache_size_kb: SQLite page cache size in KB (negative = KB, positive = pages of 4KB each)
// Default 2000KB is too small for a busy relay; 65536KB (64MB) keeps hot data in memory
{"sqlite_cache_size_kb", "65536"},
// NIP-59 Gift Wrap Timestamp Configuration // NIP-59 Gift Wrap Timestamp Configuration
{"nip59_timestamp_max_delay_sec", "0"}, {"nip59_timestamp_max_delay_sec", "0"},
+34
View File
@@ -566,6 +566,40 @@ int init_database(const char* database_path_override) {
DEBUG_LOG("SQLite WAL mode enabled"); DEBUG_LOG("SQLite WAL mode enabled");
} }
// Apply SQLite performance tuning PRAGMAs from config
// mmap_size: memory-map the database file to eliminate pread64 syscall overhead
// Default 256MB covers most relay databases; set to 0 to disable
long mmap_size = get_config_int("sqlite_mmap_size", 268435456);
if (mmap_size > 0) {
char mmap_pragma[64];
snprintf(mmap_pragma, sizeof(mmap_pragma), "PRAGMA mmap_size=%ld;", mmap_size);
char* mmap_error = NULL;
rc = sqlite3_exec(g_db, mmap_pragma, NULL, NULL, &mmap_error);
if (rc != SQLITE_OK) {
DEBUG_WARN("Failed to set mmap_size: %s", mmap_error ? mmap_error : "unknown");
if (mmap_error) sqlite3_free(mmap_error);
} else {
DEBUG_LOG("SQLite mmap_size set to %ld bytes", mmap_size);
}
}
// cache_size_kb: page cache size in KB (negative value = KB, positive = number of 4KB pages)
// Default 64MB keeps hot event data in memory and reduces repeated disk reads
int cache_size_kb = get_config_int("sqlite_cache_size_kb", 65536);
if (cache_size_kb != 0) {
char cache_pragma[64];
// Use negative value so SQLite interprets it as KB rather than page count
snprintf(cache_pragma, sizeof(cache_pragma), "PRAGMA cache_size=-%d;", cache_size_kb > 0 ? cache_size_kb : -cache_size_kb);
char* cache_error = NULL;
rc = sqlite3_exec(g_db, cache_pragma, NULL, NULL, &cache_error);
if (rc != SQLITE_OK) {
DEBUG_WARN("Failed to set cache_size: %s", cache_error ? cache_error : "unknown");
if (cache_error) sqlite3_free(cache_error);
} else {
DEBUG_LOG("SQLite cache_size set to %d KB", cache_size_kb);
}
}
DEBUG_TRACE("Exiting init_database() - success"); DEBUG_TRACE("Exiting init_database() - success");
return 0; return 0;
} }
+2 -2
View File
@@ -13,8 +13,8 @@
// Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros // Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros
#define CRELAY_VERSION_MAJOR 1 #define CRELAY_VERSION_MAJOR 1
#define CRELAY_VERSION_MINOR 2 #define CRELAY_VERSION_MINOR 2
#define CRELAY_VERSION_PATCH 6 #define CRELAY_VERSION_PATCH 7
#define CRELAY_VERSION "v1.2.6" #define CRELAY_VERSION "v1.2.7"
// Relay metadata (authoritative source for NIP-11 information) // Relay metadata (authoritative source for NIP-11 information)
#define RELAY_NAME "C-Relay" #define RELAY_NAME "C-Relay"