diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 7f55d8909..ca1e8be59 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -119,7 +119,7 @@ namespace Flow.Launcher.Infrastructure { var resultList = WordsHelper.GetPinyinList(content); var resultBuilder = new StringBuilder(_settings.UseDoublePinyin ? 3 : 4); // Pre-allocate with estimated capacity - var map = new TranslationMapping(); + var map = new TranslationMapping(resultList.Length); var previousIsChinese = false; @@ -157,10 +157,7 @@ namespace Flow.Launcher.Infrastructure map.EndConstruct(); - var translation = resultBuilder.ToString(); - var result = (translation, map); - - return _pinyinCache[content] = result; + return _pinyinCache[content] = (resultBuilder.ToString(), map); } /// diff --git a/Flow.Launcher.Infrastructure/TranslationMapping.cs b/Flow.Launcher.Infrastructure/TranslationMapping.cs index e70443077..1d8cdc615 100644 --- a/Flow.Launcher.Infrastructure/TranslationMapping.cs +++ b/Flow.Launcher.Infrastructure/TranslationMapping.cs @@ -9,18 +9,38 @@ namespace Flow.Launcher.Infrastructure // Assuming one original item maps to multi translated items // list[i] is the last translated index + 1 of original index i - private readonly List _originalToTranslated = new(); + // Using short instead of int to save memory + private List _originalToTranslatedBuilder; + private short[] _originalToTranslated; + + public TranslationMapping(int capacityHint = 16) + { + _originalToTranslatedBuilder = new List(capacityHint); + } public void AddNewIndex(int translatedIndex, int length) { if (_isConstructed) throw new InvalidOperationException("Mapping shouldn't be changed after construction"); - _originalToTranslated.Add(translatedIndex + length); + + var value = translatedIndex + length; + if (value > short.MaxValue) + throw new ArgumentOutOfRangeException(nameof(translatedIndex), + "Translation index exceeds maximum supported value (32,767)"); + + _originalToTranslatedBuilder.Add((short)value); } public int MapToOriginalIndex(int translatedIndex) { - var searchResult = _originalToTranslated.BinarySearch(translatedIndex); + if (_originalToTranslated == null) + throw new InvalidOperationException("Mapping must be constructed before use"); + + if (translatedIndex > short.MaxValue) + throw new ArgumentOutOfRangeException(nameof(translatedIndex), + "Translation index exceeds maximum supported value (32,767)"); + + var searchResult = Array.BinarySearch(_originalToTranslated, (short)translatedIndex); return searchResult >= 0 ? searchResult + 1 : ~searchResult; } @@ -28,6 +48,10 @@ namespace Flow.Launcher.Infrastructure { if (_isConstructed) throw new InvalidOperationException("Mapping has already been constructed"); + + // Convert to array to save memory (no List overhead, no excess capacity) + _originalToTranslated = _originalToTranslatedBuilder.ToArray(); + _originalToTranslatedBuilder = null; // Allow GC to collect the List _isConstructed = true; } } diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs index a3c0026c0..0ec7021ff 100644 --- a/Flow.Launcher.Test/TranslationMappingTest.cs +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -57,15 +57,15 @@ namespace Flow.Launcher.Test private static int GetOriginalToTranslatedCount(TranslationMapping mapping) { var field = typeof(TranslationMapping).GetField("_originalToTranslated", BindingFlags.NonPublic | BindingFlags.Instance); - var list = (List)field.GetValue(mapping); - return list.Count; + var array = (short[])field.GetValue(mapping); + return array.Length; } private static int GetOriginalToTranslatedAt(TranslationMapping mapping, int index) { var field = typeof(TranslationMapping).GetField("_originalToTranslated", BindingFlags.NonPublic | BindingFlags.Instance); - var list = (List)field.GetValue(mapping); - return list[index]; + var array = (short[])field.GetValue(mapping); + return array[index]; } } }