Improved further memory usage and added a subsystem for the collector to dump into a file data while it keeps the pre-processor going
This commit is contained in:
parent
2930581d25
commit
54243f0932
@ -47,6 +47,11 @@
|
|||||||
"spawnPointToleranceForForced": 99.5,
|
"spawnPointToleranceForForced": 99.5,
|
||||||
"looseLootCountTolerancePercentage": 75
|
"looseLootCountTolerancePercentage": 75
|
||||||
},
|
},
|
||||||
|
"collectorConfig": {
|
||||||
|
"collectorType": "Dump",
|
||||||
|
"maxEntitiesBeforeDumping": 1000,
|
||||||
|
"dumpLocation": "C:\\Users\\USER\\SPT\\tmp"
|
||||||
|
},
|
||||||
"writerConfig": {
|
"writerConfig": {
|
||||||
"outputLocation": "E:\\spt\\dumps\\output"
|
"outputLocation": "E:\\spt\\dumps\\output"
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using LootDumpProcessor.Model.Processing;
|
using LootDumpProcessor.Model.Processing;
|
||||||
|
using LootDumpProcessor.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LootDumpProcessor.Model;
|
namespace LootDumpProcessor.Model;
|
||||||
@ -26,7 +27,7 @@ public class ComposedKey
|
|||||||
.Cast<string>()
|
.Cast<string>()
|
||||||
.Select(i => (double)i.GetHashCode())
|
.Select(i => (double)i.GetHashCode())
|
||||||
.Sum()
|
.Sum()
|
||||||
.ToString() ?? Guid.NewGuid().ToString();
|
.ToString() ?? KeyGenerator.GetNextKey();
|
||||||
FirstItem = items?[0];
|
FirstItem = items?[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
Model/Config/CollectorConfig.cs
Normal file
20
Model/Config/CollectorConfig.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using LootDumpProcessor.Process.Collector;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace LootDumpProcessor.Model.Config;
|
||||||
|
|
||||||
|
public class CollectorConfig
|
||||||
|
{
|
||||||
|
[JsonProperty("collectorType")]
|
||||||
|
[JsonPropertyName("collectorType")]
|
||||||
|
public CollectorType CollectorType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("maxEntitiesBeforeDumping")]
|
||||||
|
[JsonPropertyName("maxEntitiesBeforeDumping")]
|
||||||
|
public int MaxEntitiesBeforeDumping { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("dumpLocation")]
|
||||||
|
[JsonPropertyName("dumpLocation")]
|
||||||
|
public string DumpLocation { get; set; }
|
||||||
|
}
|
@ -49,6 +49,10 @@ public class Config
|
|||||||
[JsonProperty("writerConfig")]
|
[JsonProperty("writerConfig")]
|
||||||
[JsonPropertyName("writerConfig")]
|
[JsonPropertyName("writerConfig")]
|
||||||
public WriterConfig WriterConfig { get; set; }
|
public WriterConfig WriterConfig { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("collectorConfig")]
|
||||||
|
[JsonPropertyName("collectorConfig")]
|
||||||
|
public CollectorConfig CollectorConfig { get; set; }
|
||||||
|
|
||||||
[JsonProperty("containerIgnoreList")]
|
[JsonProperty("containerIgnoreList")]
|
||||||
[JsonPropertyName("containerIgnoreList")]
|
[JsonPropertyName("containerIgnoreList")]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using LootDumpProcessor.Storage;
|
using LootDumpProcessor.Storage;
|
||||||
|
using LootDumpProcessor.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LootDumpProcessor.Model.Processing;
|
namespace LootDumpProcessor.Model.Processing;
|
||||||
@ -8,7 +9,7 @@ public class LooseLootCounts : IKeyable
|
|||||||
{
|
{
|
||||||
[JsonProperty("__id__")]
|
[JsonProperty("__id__")]
|
||||||
[JsonPropertyName("__id__")]
|
[JsonPropertyName("__id__")]
|
||||||
public string __ID { get; set; } = Guid.NewGuid().ToString();
|
public string __ID { get; set; } = KeyGenerator.GetNextKey();
|
||||||
|
|
||||||
public IKey Counts { get; set; }
|
public IKey Counts { get; set; }
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ namespace LootDumpProcessor.Model
|
|||||||
{
|
{
|
||||||
[Newtonsoft.Json.JsonIgnore]
|
[Newtonsoft.Json.JsonIgnore]
|
||||||
[System.Text.Json.Serialization.JsonIgnore]
|
[System.Text.Json.Serialization.JsonIgnore]
|
||||||
public string __ID { get; } = Guid.NewGuid().ToString();
|
public string __ID { get; } = KeyGenerator.GetNextKey();
|
||||||
|
|
||||||
[JsonProperty("Id", NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty("Id", NullValueHandling = NullValueHandling.Ignore)]
|
||||||
[JsonPropertyName("Id")]
|
[JsonPropertyName("Id")]
|
||||||
|
@ -2,9 +2,16 @@
|
|||||||
|
|
||||||
public static class CollectorFactory
|
public static class CollectorFactory
|
||||||
{
|
{
|
||||||
|
private static ICollector? _collector;
|
||||||
public static ICollector GetInstance()
|
public static ICollector GetInstance()
|
||||||
{
|
{
|
||||||
// TODO: implement real factory
|
if (_collector == null)
|
||||||
return new HashSetCollector();
|
_collector = LootDumpProcessorContext.GetConfig().CollectorConfig.CollectorType switch
|
||||||
|
{
|
||||||
|
CollectorType.Memory => new HashSetCollector(),
|
||||||
|
CollectorType.Dump => new DumpCollector(),
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
return _collector;
|
||||||
}
|
}
|
||||||
}
|
}
|
7
Process/Collector/CollectorType.cs
Normal file
7
Process/Collector/CollectorType.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace LootDumpProcessor.Process.Collector;
|
||||||
|
|
||||||
|
public enum CollectorType
|
||||||
|
{
|
||||||
|
Memory,
|
||||||
|
Dump
|
||||||
|
}
|
45
Process/Collector/DumpCollector.cs
Normal file
45
Process/Collector/DumpCollector.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using LootDumpProcessor.Model.Processing;
|
||||||
|
using LootDumpProcessor.Serializers.Json;
|
||||||
|
|
||||||
|
namespace LootDumpProcessor.Process.Collector;
|
||||||
|
|
||||||
|
public class DumpCollector : ICollector
|
||||||
|
{
|
||||||
|
private static readonly string DumpLocation = $"{LootDumpProcessorContext.GetConfig().CollectorConfig.DumpLocation}/collector/";
|
||||||
|
private readonly List<PartialData> processedDumps = new(LootDumpProcessorContext.GetConfig().CollectorConfig.MaxEntitiesBeforeDumping + 50);
|
||||||
|
private readonly object lockObject = new();
|
||||||
|
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(DumpLocation))
|
||||||
|
{
|
||||||
|
Directory.Delete(DumpLocation, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(DumpLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Hold(PartialData parsedDump)
|
||||||
|
{
|
||||||
|
lock (lockObject)
|
||||||
|
{
|
||||||
|
processedDumps.Add(parsedDump);
|
||||||
|
if (processedDumps.Count > LootDumpProcessorContext.GetConfig().CollectorConfig.MaxEntitiesBeforeDumping)
|
||||||
|
{
|
||||||
|
var fileName = $"collector-{DateTime.Now.ToString("yyyyMMddHHmmssfffff")}.json";
|
||||||
|
File.WriteAllText($"{DumpLocation}{fileName}", JsonSerializerFactory.GetInstance().Serialize(processedDumps));
|
||||||
|
processedDumps.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PartialData> Retrieve()
|
||||||
|
{
|
||||||
|
foreach (var file in Directory.GetFiles(DumpLocation))
|
||||||
|
{
|
||||||
|
processedDumps.AddRange(JsonSerializerFactory.GetInstance().Deserialize<List<PartialData>>(File.ReadAllText(file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return processedDumps;
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,9 @@ namespace LootDumpProcessor.Process.Collector;
|
|||||||
|
|
||||||
public class HashSetCollector : ICollector
|
public class HashSetCollector : ICollector
|
||||||
{
|
{
|
||||||
private readonly HashSet<PartialData> processedDumps = new();
|
private readonly HashSet<PartialData> processedDumps = new(100_000);
|
||||||
|
|
||||||
private readonly object lockObject = new();
|
private readonly object lockObject = new();
|
||||||
|
|
||||||
|
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
public static class FileProcessorFactory
|
public static class FileProcessorFactory
|
||||||
{
|
{
|
||||||
private static IFileProcessor _fileProcessor;
|
private static IFileProcessor? _fileProcessor;
|
||||||
public static IFileProcessor GetInstance()
|
public static IFileProcessor GetInstance()
|
||||||
{
|
{
|
||||||
// TODO: implement actual factory someday
|
// TODO: implement actual factory someday
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using LootDumpProcessor.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LootDumpProcessor.Storage.Collections;
|
namespace LootDumpProcessor.Storage.Collections;
|
||||||
@ -7,10 +8,10 @@ public class FlatKeyableDictionary<K, V> : Dictionary<K, V>, IKeyable
|
|||||||
{
|
{
|
||||||
[JsonProperty("__id__")]
|
[JsonProperty("__id__")]
|
||||||
[JsonPropertyName("__id__")]
|
[JsonPropertyName("__id__")]
|
||||||
public string __ID { get; set; } = Guid.NewGuid().ToString();
|
public string __ID { get; set; } = KeyGenerator.GetNextKey();
|
||||||
|
|
||||||
public IKey GetKey()
|
public IKey GetKey()
|
||||||
{
|
{
|
||||||
return new FlatUniqueKey(new[] { __ID });
|
return new FlatUniqueKey([__ID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
namespace LootDumpProcessor.Storage.Collections;
|
using LootDumpProcessor.Utils;
|
||||||
|
|
||||||
|
namespace LootDumpProcessor.Storage.Collections;
|
||||||
|
|
||||||
public class FlatKeyableList<T> : List<T>, IKeyable
|
public class FlatKeyableList<T> : List<T>, IKeyable
|
||||||
{
|
{
|
||||||
public string __ID { get; } = Guid.NewGuid().ToString();
|
public string __ID { get; } = KeyGenerator.GetNextKey();
|
||||||
|
|
||||||
public IKey GetKey()
|
public IKey GetKey()
|
||||||
{
|
{
|
||||||
return new FlatUniqueKey(new[] { __ID });
|
return new FlatUniqueKey([__ID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using LootDumpProcessor.Utils;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LootDumpProcessor.Storage.Collections;
|
namespace LootDumpProcessor.Storage.Collections;
|
||||||
@ -7,7 +8,7 @@ public class SubdivisionedKeyableDictionary<K, V> : Dictionary<K, V>, IKeyable
|
|||||||
{
|
{
|
||||||
[JsonProperty("__id__")]
|
[JsonProperty("__id__")]
|
||||||
[JsonPropertyName("__id__")]
|
[JsonPropertyName("__id__")]
|
||||||
public string __ID { get; set; } = Guid.NewGuid().ToString();
|
public string __ID { get; set; } = KeyGenerator.GetNextKey();
|
||||||
|
|
||||||
[JsonProperty("extras")]
|
[JsonProperty("extras")]
|
||||||
[JsonPropertyName("extras")]
|
[JsonPropertyName("extras")]
|
||||||
@ -38,10 +39,8 @@ public class SubdivisionedKeyableDictionary<K, V> : Dictionary<K, V>, IKeyable
|
|||||||
subdivisions.Add(__ID);
|
subdivisions.Add(__ID);
|
||||||
return new SubdivisionedUniqueKey(subdivisions.ToArray());
|
return new SubdivisionedUniqueKey(subdivisions.ToArray());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return new SubdivisionedUniqueKey(["dictionaries", __ID]);
|
||||||
return new SubdivisionedUniqueKey(new[] { "dictionaries", __ID });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddExtraSubdivisions(string[] extras)
|
public void AddExtraSubdivisions(string[] extras)
|
||||||
|
15
Utils/KeyGenerator.cs
Normal file
15
Utils/KeyGenerator.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace LootDumpProcessor.Utils;
|
||||||
|
|
||||||
|
public class KeyGenerator
|
||||||
|
{
|
||||||
|
private static long currentKey = 0L;
|
||||||
|
private static object lockObject = new();
|
||||||
|
|
||||||
|
public static string GetNextKey()
|
||||||
|
{
|
||||||
|
lock (lockObject)
|
||||||
|
{
|
||||||
|
return $"{++currentKey}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user