I have a project where I have to store 16 objects, each containing a list of 185 000 double
's. Overall size of the saved object should be around 20-30 mb (sizeof(double) * 16 * 185 000
), but when I try to retrieve it from database, the database allocates 200 mb to retrieve this 20-30 mb object.
My questions are:
- Is this expected behaviour?
- How can I avoid such huge allocation of memory when I just want to retrieve one document?
Here is fully replicable example and screenshots of profiler:
class Program
{
private static string _path;
static void Main(string[] args)
{
_path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "testDb");
// Comment after first insert to avoid adding the same object.
AddData();
var data = GetData();
Console.ReadLine();
}
public static void AddData()
{
var items = new List<Item>();
for (var index = 0; index < 16; index++)
{
var item = new Item {Values = Enumerable.Range(0, 185_000).Select(v => (double) v).ToList()};
items.Add(item);
}
var testData = new TestClass { Name = "Test1", Items = items.ToList() };
using (var db = new LiteDatabase(_path))
{
var collection = db.GetCollection<TestClass>();
collection.Insert(testData);
}
}
public static TestClass GetData()
{
using (var db = new LiteDatabase(_path))
{
var collection = db.GetCollection<TestClass>();
// This line causes huge memory allocation and wakes up garbage collector many many times.
return collection.FindOne(Query.EQ(nameof(TestClass.Name), "Test1"));
}
}
}
public class TestClass
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Item> Items { get; set; }
}
public class Item
{
public IList<double> Values { get; set; }
}
Changing 185_000
to 1_850_000
makes my RAM usage go to >4GB(!)