From c08311857fa34fecefdaca2a9f35bb72806b95e0 Mon Sep 17 00:00:00 2001 From: iht Date: Sun, 25 May 2025 23:40:08 +0200 Subject: [PATCH 1/4] Memory usage optimizations --- ImperatorToCK3/CK3/Dynasties/Dynasty.cs | 2 +- ImperatorToCK3/Imperator/Characters/Character.cs | 6 +++--- ImperatorToCK3/Imperator/Countries/CountryFactory.cs | 4 ++-- ImperatorToCK3/Imperator/Countries/RulerTerm.cs | 4 ++-- ImperatorToCK3/Imperator/Families/Family.cs | 2 +- ImperatorToCK3/Imperator/Pops/Pop.cs | 6 +++--- ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ImperatorToCK3/CK3/Dynasties/Dynasty.cs b/ImperatorToCK3/CK3/Dynasties/Dynasty.cs index 79e333c21..1c2f84f6f 100644 --- a/ImperatorToCK3/CK3/Dynasties/Dynasty.cs +++ b/ImperatorToCK3/CK3/Dynasties/Dynasty.cs @@ -64,7 +64,7 @@ public Dynasty(string dynastyId, BufferedReader dynastyReader) { var parser = new Parser(); parser.RegisterKeyword("prefix", reader => Prefix = reader.GetString()); parser.RegisterKeyword("name", reader => Name = reader.GetString()); - parser.RegisterKeyword("culture", reader => CultureId = reader.GetString()); + parser.RegisterKeyword("culture", reader => CultureId = string.Intern(reader.GetString())); parser.RegisterKeyword("motto", reader => Motto = reader.GetString()); parser.RegisterKeyword("forced_coa_religiongroup", reader => ForcedCoaReligionGroup = reader.GetString()); parser.IgnoreAndLogUnregisteredItems(); diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index cd8f500c3..25d7fd5c0 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -120,8 +120,8 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) parser.RegisterKeyword("country", reader => character.parsedCountryId = reader.GetULong()); parser.RegisterKeyword("home_country", reader => character.parsedHomeCountryId = reader.GetULong()); parser.RegisterKeyword("province", reader => character.ProvinceId = reader.GetULong()); - parser.RegisterKeyword("culture", reader => character.culture = reader.GetString()); - parser.RegisterKeyword("religion", reader => character.Religion = reader.GetString()); + parser.RegisterKeyword("culture", reader => character.culture = string.Intern(reader.GetString())); + parser.RegisterKeyword("religion", reader => character.Religion = string.Intern(reader.GetString())); parser.RegisterKeyword("fertility", reader => character.Fertility = reader.GetDouble()); parser.RegisterKeyword("health", reader => character.Health = reader.GetDouble()); parser.RegisterKeyword("family", reader => character.parsedFamilyId = reader.GetULong()); @@ -171,7 +171,7 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) var variablesParser = new Parser(); variablesParser.RegisterKeyword("data", dataReader => { var blobParser = new Parser(); - blobParser.RegisterKeyword("flag", blobReader => variables.Add(blobReader.GetString())); + blobParser.RegisterKeyword("flag", blobReader => variables.Add(string.Intern(blobReader.GetString()))); blobParser.IgnoreUnregisteredItems(); foreach (var blob in new BlobList(dataReader).Blobs) { diff --git a/ImperatorToCK3/Imperator/Countries/CountryFactory.cs b/ImperatorToCK3/Imperator/Countries/CountryFactory.cs index ed23f893d..906c632be 100644 --- a/ImperatorToCK3/Imperator/Countries/CountryFactory.cs +++ b/ImperatorToCK3/Imperator/Countries/CountryFactory.cs @@ -49,8 +49,8 @@ private static void RegisterCountryKeywords(Parser parser, Country parsedCountry .GroupBy(a => a.Key) .ToFrozenDictionary(g => g.Key, g => int.Parse(g.Last().Value)); }); - parser.RegisterKeyword("primary_culture", reader => parsedCountry.PrimaryCulture = reader.GetString()); - parser.RegisterKeyword("religion", reader => parsedCountry.Religion = reader.GetString()); + parser.RegisterKeyword("primary_culture", reader => parsedCountry.PrimaryCulture = string.Intern(reader.GetString())); + parser.RegisterKeyword("religion", reader => parsedCountry.Religion = string.Intern(reader.GetString())); parser.RegisterKeyword("government_key", reader => SetGovernmentType(reader, parsedCountry)); parser.RegisterKeyword("family", reader => parsedCountry.parsedFamilyIds.Add(reader.GetULong())); parser.RegisterKeyword("minor_family", reader => parsedCountry.parsedFamilyIds.Add(reader.GetULong())); diff --git a/ImperatorToCK3/Imperator/Countries/RulerTerm.cs b/ImperatorToCK3/Imperator/Countries/RulerTerm.cs index bca25f8cf..e455bc8da 100644 --- a/ImperatorToCK3/Imperator/Countries/RulerTerm.cs +++ b/ImperatorToCK3/Imperator/Countries/RulerTerm.cs @@ -59,8 +59,8 @@ public RulerTerm(BufferedReader prehistoryRulerReader, CountryCollection countri var dateStr = reader.GetString(); StartDate = new Date(dateStr, AUC: true); }); - prehistoryParser.RegisterKeyword("religion", reader => PreImperatorRuler.Religion = reader.GetString()); - prehistoryParser.RegisterKeyword("culture", reader => PreImperatorRuler.Culture = reader.GetString()); + prehistoryParser.RegisterKeyword("religion", reader => PreImperatorRuler.Religion = string.Intern(reader.GetString())); + prehistoryParser.RegisterKeyword("culture", reader => PreImperatorRuler.Culture = string.Intern(reader.GetString())); prehistoryParser.RegisterKeyword("nickname", reader => PreImperatorRuler.Nickname = reader.GetString()); prehistoryParser.RegisterKeyword("country", reader => { var tag = reader.GetString(); diff --git a/ImperatorToCK3/Imperator/Families/Family.cs b/ImperatorToCK3/Imperator/Families/Family.cs index d62fb385a..04bcc2b5f 100644 --- a/ImperatorToCK3/Imperator/Families/Family.cs +++ b/ImperatorToCK3/Imperator/Families/Family.cs @@ -56,7 +56,7 @@ static FamilyFactory() { family.PrestigeRatio = reader.GetDouble() ); parser.RegisterKeyword("culture", reader => - family.Culture = reader.GetString() + family.Culture = string.Intern(reader.GetString()) ); parser.RegisterKeyword("minor_family", reader => family.Minor = reader.GetBool() diff --git a/ImperatorToCK3/Imperator/Pops/Pop.cs b/ImperatorToCK3/Imperator/Pops/Pop.cs index d06d6b095..f0729fb8b 100644 --- a/ImperatorToCK3/Imperator/Pops/Pop.cs +++ b/ImperatorToCK3/Imperator/Pops/Pop.cs @@ -16,9 +16,9 @@ public static Pop Parse(string idString, BufferedReader reader) { var newPop = new Pop(ulong.Parse(idString)); var parser = new Parser(); - parser.RegisterKeyword("type", r => newPop.Type = r.GetString()); - parser.RegisterKeyword("culture", r => newPop.Culture = r.GetString()); - parser.RegisterKeyword("religion", r => newPop.Religion = r.GetString()); + parser.RegisterKeyword("type", r => newPop.Type = string.Intern(r.GetString())); + parser.RegisterKeyword("culture", r => newPop.Culture = string.Intern(r.GetString())); + parser.RegisterKeyword("religion", r => newPop.Religion = string.Intern(r.GetString())); parser.RegisterRegex(CommonRegexes.Catchall, ParserHelpers.IgnoreAndLogItem); parser.ParseStream(reader); diff --git a/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs b/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs index 7cd73c8d9..bcbd2324e 100644 --- a/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs +++ b/ImperatorToCK3/Imperator/Provinces/ProvinceFactory.cs @@ -18,10 +18,10 @@ static Province() { parsedProvince.Controller = reader.GetULong() ); provinceParser.RegisterKeyword("culture", reader => - parsedProvince.Culture = reader.GetString() + parsedProvince.Culture = string.Intern(reader.GetString()) ); provinceParser.RegisterKeyword("religion", reader => - parsedProvince.ReligionId = reader.GetString() + parsedProvince.ReligionId = string.Intern(reader.GetString()) ); provinceParser.RegisterKeyword("pop", reader => parsedProvince.parsedPopIds.Add(reader.GetULong()) From 948d07cc427d9647bdc34cf5abcc0940cd4d5311 Mon Sep 17 00:00:00 2001 From: iht Date: Mon, 26 May 2025 00:20:18 +0200 Subject: [PATCH 2/4] More string interning --- .../CommonUtils/BufferedReaderExtensions.cs | 8 ++++++++ ImperatorToCK3/Imperator/Armies/Subunit.cs | 6 +++--- ImperatorToCK3/Imperator/Characters/Character.cs | 4 ++-- .../Imperator/Countries/CountryFactory.cs | 13 ++++++++----- ImperatorToCK3/Imperator/Countries/RulerTerm.cs | 2 +- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs b/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs index 5d2f66fe8..a87ec7bea 100644 --- a/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs +++ b/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs @@ -10,4 +10,12 @@ internal static Dictionary GetAssignmentsAsDict(this BufferedRea .GroupBy(a => a.Key) .ToDictionary(g => g.Key, g => g.Last().Value); } + + internal static List GetAndInternStrings(this BufferedReader reader) { + var strings = new List(); + foreach (var str in reader.GetStrings()) { + string.Intern(str); + } + return strings; + } } \ No newline at end of file diff --git a/ImperatorToCK3/Imperator/Armies/Subunit.cs b/ImperatorToCK3/Imperator/Armies/Subunit.cs index fbf89286b..91792038b 100644 --- a/ImperatorToCK3/Imperator/Armies/Subunit.cs +++ b/ImperatorToCK3/Imperator/Armies/Subunit.cs @@ -14,8 +14,8 @@ public Subunit(ulong id, BufferedReader subunitReader) { Id = id; var parser = new Parser(); - parser.RegisterKeyword("category", reader => Category = reader.GetString()); - parser.RegisterKeyword("type", reader => Type = reader.GetString()); + parser.RegisterKeyword("category", reader => Category = string.Intern(reader.GetString())); + parser.RegisterKeyword("type", reader => Type = string.Intern(reader.GetString())); parser.RegisterKeyword("country", reader => CountryId = reader.GetULong()); parser.RegisterKeyword("strength", reader => Strength = reader.GetDouble()); parser.IgnoreAndStoreUnregisteredItems(IgnoredTokens); @@ -23,5 +23,5 @@ public Subunit(ulong id, BufferedReader subunitReader) { parser.ParseStream(subunitReader); } - public static IgnoredKeywordsSet IgnoredTokens { get; } = new(); + public static IgnoredKeywordsSet IgnoredTokens { get; } = []; } \ No newline at end of file diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index 25d7fd5c0..d7cfdec9a 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -125,7 +125,7 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) parser.RegisterKeyword("fertility", reader => character.Fertility = reader.GetDouble()); parser.RegisterKeyword("health", reader => character.Health = reader.GetDouble()); parser.RegisterKeyword("family", reader => character.parsedFamilyId = reader.GetULong()); - parser.RegisterKeyword("traits", reader => character.Traits = reader.GetStrings()); + parser.RegisterKeyword("traits", reader => character.Traits = reader.GetAndInternStrings()); parser.RegisterKeyword("female", reader => character.Female = reader.GetBool()); parser.RegisterKeyword("children", reader => character.parsedChildrenIds = [.. reader.GetULongs()]); parser.RegisterKeyword("spouse", reader => character.parsedSpouseIds = [.. reader.GetULongs()]); @@ -146,7 +146,7 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) var dateStr = reader.GetString(); character.DeathDate = new Date(dateStr, AUC: true); // converted to AD }); - parser.RegisterKeyword("death", reader => character.DeathReason = reader.GetString()); + parser.RegisterKeyword("death", reader => character.DeathReason = string.Intern(reader.GetString())); parser.RegisterKeyword("attributes", reader => character.Attributes = CharacterAttributes.Parse(reader)); parser.RegisterKeyword("nickname", reader => character.Nickname = reader.GetString()); parser.RegisterKeyword("dna", reader => character.DNA = reader.GetString()); diff --git a/ImperatorToCK3/Imperator/Countries/CountryFactory.cs b/ImperatorToCK3/Imperator/Countries/CountryFactory.cs index 906c632be..6dc7d47d5 100644 --- a/ImperatorToCK3/Imperator/Countries/CountryFactory.cs +++ b/ImperatorToCK3/Imperator/Countries/CountryFactory.cs @@ -59,7 +59,7 @@ private static void RegisterCountryKeywords(Parser parser, Country parsedCountry var variablesParser = new Parser(); variablesParser.RegisterKeyword("data", dataReader => { var blobParser = new Parser(); - blobParser.RegisterKeyword("flag", blobReader => variables.Add(blobReader.GetString())); + blobParser.RegisterKeyword("flag", blobReader => variables.Add(string.Intern(blobReader.GetString()))); blobParser.IgnoreUnregisteredItems(); foreach (var blob in new BlobList(dataReader).Blobs) { @@ -78,9 +78,12 @@ private static void RegisterCountryKeywords(Parser parser, Country parsedCountry }); parser.RegisterKeyword("mark_invention", ParserHelpers.IgnoreItem); parser.RegisterKeyword("ruler_term", reader => parsedCountry.RulerTerms.Add(RulerTerm.Parse(reader))); - parser.RegisterRegex(monarchyLawRegexStr, reader => parsedCountry.monarchyLaws.Add(reader.GetString())); - parser.RegisterRegex(republicLawRegexStr, reader => parsedCountry.republicLaws.Add(reader.GetString())); - parser.RegisterRegex(tribalLawRegexStr, reader => parsedCountry.tribalLaws.Add(reader.GetString())); + parser.RegisterRegex(monarchyLawRegexStr, reader => + parsedCountry.monarchyLaws.Add(string.Intern(reader.GetString()))); + parser.RegisterRegex(republicLawRegexStr, reader => + parsedCountry.republicLaws.Add(string.Intern(reader.GetString()))); + parser.RegisterRegex(tribalLawRegexStr, reader => + parsedCountry.tribalLaws.Add(string.Intern(reader.GetString()))); parser.RegisterKeyword("is_antagonist", ParserHelpers.IgnoreItem); parser.RegisterKeyword("has_senior_ally", ParserHelpers.IgnoreItem); parser.RegisterKeyword("cached_happiness_for_owned", ParserHelpers.IgnoreItem); @@ -92,7 +95,7 @@ private static void RegisterCountryKeywords(Parser parser, Country parsedCountry } private static void SetGovernmentType(BufferedReader reader, Country parsedCountry) { - var governmentStr = reader.GetString(); + var governmentStr = string.Intern(reader.GetString()); parsedCountry.Government = governmentStr; // set government type if (monarchyGovernments.Contains(governmentStr)) { diff --git a/ImperatorToCK3/Imperator/Countries/RulerTerm.cs b/ImperatorToCK3/Imperator/Countries/RulerTerm.cs index e455bc8da..c0abf9301 100644 --- a/ImperatorToCK3/Imperator/Countries/RulerTerm.cs +++ b/ImperatorToCK3/Imperator/Countries/RulerTerm.cs @@ -29,7 +29,7 @@ public static RulerTerm Parse(BufferedReader reader) { var dateString = r.GetString(); newTerm.StartDate = new Date(dateString, AUC: true); }); - parser.RegisterKeyword("government", r => newTerm.Government = r.GetString()); + parser.RegisterKeyword("government", r => newTerm.Government = string.Intern(r.GetString())); parser.RegisterRegex(CommonRegexes.Catchall, (r, token) => { IgnoredTokens.Add(token); ParserHelpers.IgnoreItem(r); From f38f7b53ac7947a609433fd7a09af225693220fe Mon Sep 17 00:00:00 2001 From: iht Date: Mon, 26 May 2025 00:23:52 +0200 Subject: [PATCH 3/4] Intern I:R nickname strings --- ImperatorToCK3/Imperator/Characters/Character.cs | 2 +- ImperatorToCK3/Imperator/Countries/RulerTerm.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ImperatorToCK3/Imperator/Characters/Character.cs b/ImperatorToCK3/Imperator/Characters/Character.cs index d7cfdec9a..aa87f8219 100644 --- a/ImperatorToCK3/Imperator/Characters/Character.cs +++ b/ImperatorToCK3/Imperator/Characters/Character.cs @@ -148,7 +148,7 @@ public static void RegisterCharacterKeywords(Parser parser, Character character) }); parser.RegisterKeyword("death", reader => character.DeathReason = string.Intern(reader.GetString())); parser.RegisterKeyword("attributes", reader => character.Attributes = CharacterAttributes.Parse(reader)); - parser.RegisterKeyword("nickname", reader => character.Nickname = reader.GetString()); + parser.RegisterKeyword("nickname", reader => character.Nickname = string.Intern(reader.GetString())); parser.RegisterKeyword("dna", reader => character.DNA = reader.GetString()); parser.RegisterKeyword("mother", reader => character.parsedMotherId = reader.GetULong()); parser.RegisterKeyword("father", reader => character.parsedFatherId = reader.GetULong()); diff --git a/ImperatorToCK3/Imperator/Countries/RulerTerm.cs b/ImperatorToCK3/Imperator/Countries/RulerTerm.cs index c0abf9301..02732ea75 100644 --- a/ImperatorToCK3/Imperator/Countries/RulerTerm.cs +++ b/ImperatorToCK3/Imperator/Countries/RulerTerm.cs @@ -61,7 +61,7 @@ public RulerTerm(BufferedReader prehistoryRulerReader, CountryCollection countri }); prehistoryParser.RegisterKeyword("religion", reader => PreImperatorRuler.Religion = string.Intern(reader.GetString())); prehistoryParser.RegisterKeyword("culture", reader => PreImperatorRuler.Culture = string.Intern(reader.GetString())); - prehistoryParser.RegisterKeyword("nickname", reader => PreImperatorRuler.Nickname = reader.GetString()); + prehistoryParser.RegisterKeyword("nickname", reader => PreImperatorRuler.Nickname = string.Intern(reader.GetString())); prehistoryParser.RegisterKeyword("country", reader => { var tag = reader.GetString(); if (tagToCountryCache.TryGetValue(tag, out var cachedCountry)) { From 027dea4eb044c9019e03c67d291061e60cd05c66 Mon Sep 17 00:00:00 2001 From: iht Date: Mon, 26 May 2025 00:42:55 +0200 Subject: [PATCH 4/4] Fix GetAndInternStrings --- ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs b/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs index a87ec7bea..d58636bd6 100644 --- a/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs +++ b/ImperatorToCK3/CommonUtils/BufferedReaderExtensions.cs @@ -14,7 +14,7 @@ internal static Dictionary GetAssignmentsAsDict(this BufferedRea internal static List GetAndInternStrings(this BufferedReader reader) { var strings = new List(); foreach (var str in reader.GetStrings()) { - string.Intern(str); + strings.Add(string.Intern(str)); } return strings; }