{"record":{"id":"7101b5a586e3b1f2","repo":"microsoft/garnet","slug":"nameof-logsettings-memorysize-must-be-at-least","errorCode":null,"errorMessage":"{nameof(logSettings.MemorySize)} must be at least {LogSettings.kMinPageCount}x the page size ({1L << logSettings.PageSizeBits})","messagePattern":"(.+?) must be at least (.+?)x the page size \\((.+?)\\)","errorType":"exception","errorClass":"TsavoriteException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs","lineNumber":560,"sourceCode":"            asyncGetFromDiskCallbackDelegate = AsyncGetFromDiskCallback;\n\n            this.transientObjectIdMap = transientObjectIdMap;\n\n            // Validation\n            if (logSettings.PageCount == 0 && logSettings.MemorySize == 0)\n                throw new TsavoriteException($\"{nameof(logSettings.PageCount)} or {nameof(logSettings.MemorySize)} must be specified\");\n            if (logSettings.PageSizeBits < LogSettings.kMinPageSizeBits || logSettings.PageSizeBits > LogSettings.kMaxPageSizeBits)\n                throw new TsavoriteException($\"{nameof(logSettings.PageSizeBits)} must be between {LogSettings.kMinPageSizeBits} and {LogSettings.kMaxPageSizeBits}\");\n            if (logSettings.PageSizeBits < PageHeader.SizeBits)\n                throw new TsavoriteException($\"{nameof(logSettings.PageSizeBits)} must be >= PageHeader.SizeBits {PageHeader.SizeBits}\");\n            if (logSettings.PageCount > MemoryUtils.ArrayMaxLength)\n                throw new TsavoriteException($\"{nameof(logSettings.PageCount)} must be less than or equal to the maximum array length ({MemoryUtils.ArrayMaxLength})\");\n            if (logSettings.SegmentSizeBits < LogSettings.kMinMainLogSegmentSizeBits || logSettings.SegmentSizeBits > LogSettings.kMaxSegmentSizeBits)\n                throw new TsavoriteException($\"{nameof(logSettings.SegmentSizeBits)} must be between {LogSettings.kMinMainLogSegmentSizeBits} and {LogSettings.kMaxSegmentSizeBits}\");\n            if (logSettings.MemorySize != 0 && (logSettings.MemorySize < 1L << LogSettings.kMinMemorySizeBits || logSettings.MemorySize > 1L << LogSettings.kMaxMemorySizeBits))\n                throw new TsavoriteException($\"{nameof(logSettings.MemorySize)} must be between {1L << LogSettings.kMinMemorySizeBits} and {1L << LogSettings.kMaxMemorySizeBits}, or may be 0 for ReadOnly TsavoriteLog\");\n            if ((logSettings.MemorySize != 0) && (logSettings.MemorySize < (1L << logSettings.PageSizeBits) * LogSettings.kMinPageCount))\n                throw new TsavoriteException($\"{nameof(logSettings.MemorySize)} must be at least {LogSettings.kMinPageCount}x the page size ({1L << logSettings.PageSizeBits})\");\n            if (logSettings.MutableFraction < 0.0 || logSettings.MutableFraction > 1.0)\n                throw new TsavoriteException($\"{nameof(logSettings.MutableFraction)} must be >= 0.0 and <= 1.0\");\n            if (logSettings.ReadCacheSettings is not null)\n            {\n                var rcs = logSettings.ReadCacheSettings;\n                if (rcs.PageCount == 0 && rcs.MemorySize == 0)\n                    throw new TsavoriteException($\"{nameof(rcs.PageCount)} or {nameof(rcs.MemorySize)} must be specified\");\n                if (rcs.PageSizeBits < LogSettings.kMinPageSizeBits || rcs.PageSizeBits > LogSettings.kMaxPageSizeBits)\n                    throw new TsavoriteException($\"{nameof(rcs.PageSizeBits)} must be between {LogSettings.kMinPageSizeBits} and {LogSettings.kMaxPageSizeBits}\");\n                if (rcs.PageCount > MemoryUtils.ArrayMaxLength)\n                    throw new TsavoriteException($\"{nameof(rcs.PageCount)} must be less than or equal to the maximum array length ({MemoryUtils.ArrayMaxLength})\");\n                if (rcs.MemorySize != 0 && (rcs.MemorySize < 1L << LogSettings.kMinMemorySizeBits || rcs.MemorySize > 1L << LogSettings.kMaxMemorySizeBits))\n                    throw new TsavoriteException($\"{nameof(rcs.MemorySize)} must be between {1L << LogSettings.kMinMemorySizeBits} and {1L << LogSettings.kMaxMemorySizeBits}\");\n                if ((rcs.MemorySize != 0) && (rcs.MemorySize < (1L << rcs.PageSizeBits) * 2))\n                    throw new TsavoriteException($\"{nameof(logSettings.MemorySize)} must be at least twice the page size ({1L << rcs.PageSizeBits})\");\n                if (rcs.SecondChanceFraction < 0.0 || rcs.SecondChanceFraction > 1.0)\n                    throw new TsavoriteException($\"{rcs.SecondChanceFraction} must be >= 0.0 and <= 1.0\");\n            }","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/Allocator/AllocatorBase.cs#L542-L578","documentation":"Constructor validation: when MemorySize is non-zero it must be at least kMinPageCount (2) times the page size (1 << PageSizeBits). The circular buffer must hold at least two pages so that flush/eviction can proceed while one page is being written. Default MemorySize (16GiB) and PageSizeBits (25 => 32MiB) give 512 pages, comfortably above the floor.","triggerScenarios":"Choosing a small MemorySize relative to a large PageSizeBits, e.g. PageSizeBits=25 (32MiB pages) with MemorySize=16MiB: 16MiB < 2 * 32MiB, so this fires.","commonSituations":"Tuning for large pages without raising MemorySize; benchmark configs that shrank MemorySize but kept big pages.","solutions":["Raise MemorySize to at least 2 * (1 << PageSizeBits).","Or lower PageSizeBits so that MemorySize >= 2 pages.","Keep the default MemorySize unless you also adjust PageSizeBits consistently."],"exampleFix":"// before\nlogSettings.PageSizeBits = 25;          // 32MiB page\nlogSettings.MemorySize  = 1L << 24;      // 16MiB -> < 2 pages\n// after\nlogSettings.MemorySize  = 1L << 26;      // 64MiB -> 2 pages, the minimum","handlingStrategy":"validation","validationCode":"// MemorySize must cover >= 2 pages (kMinPageCount).\nconst int kMinPageCount = 2;\nlong minMem = (1L << logSettings.PageSizeBits) * kMinPageCount;\nif (logSettings.MemorySize != 0 && logSettings.MemorySize < minMem)\n    logSettings.MemorySize = minMem;   // or raise PageSizeBits-adjusted floor","typeGuard":null,"tryCatchPattern":"try { new TsavoriteKV<K,V>(logSettings, ...); }\ncatch (TsavoriteException ex) when (ex.Message.Contains(\"MemorySize\") && ex.Message.Contains(\"at least\") && ex.Message.Contains(\"the page size\"))\n{ /* raise MemorySize to >= 2 * (1<<PageSizeBits) and recreate */ }","preventionTips":["When raising PageSizeBits, recompute the MemorySize floor as 2 * (1 << PageSizeBits).","Keep the default MemorySize unless you also retune PageSizeBits.","Add a unit test that asserts MemorySize >= 2 pages for your configs."],"tags":["storage","configuration","log-settings","memory","page-size"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}