Reduce memory used by parsing CLI arguments and keys

These actions are usually only performed once per program run, but the objects they used were stored as static properties where they couldn't be cleared from memory. Free up a small bit of memory by only storing them locally.

Reduces memory used by ~150 KB and reduces object count by over 1500
This commit is contained in:
Alex Barney 2019-11-02 23:15:21 -07:00
parent cccb811293
commit fcf46b1822
2 changed files with 36 additions and 24 deletions

View file

@ -492,25 +492,14 @@ namespace LibHac
{ {
private const int TitleKeySize = 0x10; private const int TitleKeySize = 0x10;
public static readonly Dictionary<string, KeyValue> CommonKeyDict;
public static readonly Dictionary<string, KeyValue> UniqueKeyDict;
public static readonly Dictionary<string, KeyValue> AllKeyDict;
static ExternalKeyReader()
{
List<KeyValue> commonKeys = CreateCommonKeyList();
List<KeyValue> uniqueKeys = CreateUniqueKeyList();
CommonKeyDict = commonKeys.ToDictionary(k => k.Name, k => k);
UniqueKeyDict = uniqueKeys.ToDictionary(k => k.Name, k => k);
AllKeyDict = uniqueKeys.Concat(commonKeys).ToDictionary(k => k.Name, k => k);
}
public static void ReadKeyFile(Keyset keyset, string filename, string titleKeysFilename = null, string consoleKeysFilename = null, IProgressReport logger = null) public static void ReadKeyFile(Keyset keyset, string filename, string titleKeysFilename = null, string consoleKeysFilename = null, IProgressReport logger = null)
{ {
if (filename != null) ReadMainKeys(keyset, filename, AllKeyDict, logger); Dictionary<string, KeyValue> keyDictionary = CreateFullKeyDictionary();
if (consoleKeysFilename != null) ReadMainKeys(keyset, consoleKeysFilename, AllKeyDict, logger);
if (filename != null) ReadMainKeys(keyset, filename, keyDictionary, logger);
if (consoleKeysFilename != null) ReadMainKeys(keyset, consoleKeysFilename, keyDictionary, logger);
if (titleKeysFilename != null) ReadTitleKeys(keyset, titleKeysFilename, logger); if (titleKeysFilename != null) ReadTitleKeys(keyset, titleKeysFilename, logger);
keyset.ExternalKeySet.TrimExcess(); keyset.ExternalKeySet.TrimExcess();
keyset.DeriveKeys(logger); keyset.DeriveKeys(logger);
} }
@ -526,13 +515,15 @@ namespace LibHac
public static void LoadConsoleKeys(this Keyset keyset, string filename, IProgressReport logger = null) public static void LoadConsoleKeys(this Keyset keyset, string filename, IProgressReport logger = null)
{ {
foreach (KeyValue key in UniqueKeyDict.Values) Dictionary<string, KeyValue> uniqueKeyDictionary = CreateUniqueKeyDictionary();
foreach (KeyValue key in uniqueKeyDictionary.Values)
{ {
byte[] keyBytes = key.GetKey(keyset); byte[] keyBytes = key.GetKey(keyset);
Array.Clear(keyBytes, 0, keyBytes.Length); Array.Clear(keyBytes, 0, keyBytes.Length);
} }
ReadMainKeys(keyset, filename, UniqueKeyDict, logger); ReadMainKeys(keyset, filename, uniqueKeyDictionary, logger);
keyset.DeriveKeys(); keyset.DeriveKeys();
} }
@ -650,17 +641,17 @@ namespace LibHac
public static string PrintCommonKeys(Keyset keyset) public static string PrintCommonKeys(Keyset keyset)
{ {
return PrintKeys(keyset, CommonKeyDict); return PrintKeys(keyset, CreateCommonKeyDictionary());
} }
public static string PrintUniqueKeys(Keyset keyset) public static string PrintUniqueKeys(Keyset keyset)
{ {
return PrintKeys(keyset, UniqueKeyDict); return PrintKeys(keyset, CreateUniqueKeyDictionary());
} }
public static string PrintAllKeys(Keyset keyset) public static string PrintAllKeys(Keyset keyset)
{ {
return PrintKeys(keyset, AllKeyDict); return PrintKeys(keyset, CreateFullKeyDictionary());
} }
public static string PrintTitleKeys(Keyset keyset) public static string PrintTitleKeys(Keyset keyset)
@ -676,6 +667,24 @@ namespace LibHac
return sb.ToString(); return sb.ToString();
} }
public static Dictionary<string, KeyValue> CreateCommonKeyDictionary()
{
return CreateCommonKeyList().ToDictionary(k => k.Name, k => k);
}
public static Dictionary<string, KeyValue> CreateUniqueKeyDictionary()
{
return CreateUniqueKeyList().ToDictionary(k => k.Name, k => k);
}
public static Dictionary<string, KeyValue> CreateFullKeyDictionary()
{
List<KeyValue> commonKeys = CreateCommonKeyList();
List<KeyValue> uniqueKeys = CreateUniqueKeyList();
return uniqueKeys.Concat(commonKeys).ToDictionary(k => k.Name, k => k);
}
private static List<KeyValue> CreateCommonKeyList() private static List<KeyValue> CreateCommonKeyList()
{ {
var keys = new List<KeyValue> var keys = new List<KeyValue>

View file

@ -7,7 +7,7 @@ namespace hactoolnet
{ {
internal static class CliParser internal static class CliParser
{ {
private static readonly CliOption[] CliOptions = private static CliOption[] GetCliOptions() => new[]
{ {
new CliOption("custom", 0, (o, a) => o.RunCustom = true), new CliOption("custom", 0, (o, a) => o.RunCustom = true),
new CliOption("intype", 't', 1, (o, a) => o.InFileType = ParseFileType(a[0])), new CliOption("intype", 't', 1, (o, a) => o.InFileType = ParseFileType(a[0])),
@ -73,6 +73,8 @@ namespace hactoolnet
var options = new Options(); var options = new Options();
bool inputSpecified = false; bool inputSpecified = false;
CliOption[] cliOptions = GetCliOptions();
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
{ {
string arg; string arg;
@ -98,7 +100,7 @@ namespace hactoolnet
continue; continue;
} }
CliOption option = CliOptions.FirstOrDefault(x => x.Long == arg || x.Short == arg); CliOption option = cliOptions.FirstOrDefault(x => x.Long == arg || x.Short == arg);
if (option == null) if (option == null)
{ {
PrintWithUsage($"Unknown option {args[i]}"); PrintWithUsage($"Unknown option {args[i]}");
@ -260,6 +262,7 @@ namespace hactoolnet
ArgsNeeded = argsNeeded; ArgsNeeded = argsNeeded;
Assigner = assigner; Assigner = assigner;
} }
public CliOption(string longName, int argsNeeded, Action<Options, string[]> assigner) public CliOption(string longName, int argsNeeded, Action<Options, string[]> assigner)
{ {
Long = longName; Long = longName;