Здравсвуйте,
На ПК-сервере есть 4GB оперативки, .net core приложение.
Есть объект с кучей вложенных списков/объектов ~3GB / (~700к вложенных объектов верхнего уровня).
class Bar {
public string Name {get; set}
public string Value {get; set}
public Other Other {get; set}
}
class Foo{
public List<Bar> Bars{get; set;}
}
Отдельно от него есть несколько десятков списков(~300mb) разной величины (до 300к строк) по которым происходит поиск данных:
public List<string> CoolNames {get; set;}
// Поиск
var bars=_foo.Bars.Where(x=> CoolNames.Contains(x.Name));
Все эти объекты хранятся в памяти и больше не меняются. Надо соптимизировать поиск данных и колличество исспользуемой памяти.
Есть несколько идей:
1. В классе `Bar`, `Name` сделать `int` типом и добавить соответствующий `CoolName` класс.
class Bar {
public Name {get; set;}
}
class CoolName{
public int Id {get;set;}
public string Name {get; set;}
}
public List<CoolName> CoolNames {get; set;}
// Поиск
var coolName=CoolNames.Single(x=>x.Name="...");
var bars=_foo.Bars.Where(x=> x.Name == coolName.Id);
2. Что бы строки в списке `CoolNames` и `Bar.Name` были одни и те же,
что бы искать нужну строку по ссылке, а не по значению, надо
удалить все строки из объектов `Bar.Name` и заменить их на строки из `CoolNames`
CoolNames.ForEach(coolName=> {
_foo.Bars.ForEach(bar=>{
if(coolName==bar.Name){ // сейчас идет сравнение по значению
bar.Name=coolName;
}
});
});
var bars=_foo.Bars.Where(x=> CoolNames.Any(y=>(object)y == (object)x.Name)); // теперь должен быть поиск по сслыке.
3. Почти такой же вариант как и в во втором случае, только сделать строки Intern.
CoolNames=CoolName.Select(x=> string.Intern(x)).ToList();
_foo.Bars.ForEach(bar=>{
bar.Name=string.Intern(bar.Name);
});
var bars=_foo.Bars.Where(x=> CoolNames.Any(y=>(object)y == (object)x.Name)); // теперь должен быть поиск по сслыке.
--
Все объекты будут жить до конца жизни приложения, бд ставить на ПК — не вариант.
Какой из приведенных вариантов лучше всего? Какие еще идеи?