У меня есть приложение, в котором вход был увеличен с 50K записей местоположения до 1,1 миллиона записей местоположения. Это вызвало серьезные проблемы, так как весь файл был ранее де-сериализован в один объект. Размер объекта ~ 1 ГБ для производства, такого как файл с 1,1 миллионами записей. Из-за проблем с большими объектами GC я хочу сохранить де-сериализованный объект под отметкой 85K.Проблемы с обработкой 1GB json-файла с использованием JSON.NET
Я пытаюсь разобрать один объект местоположения за один раз и де-сериализовать его, чтобы я мог контролировать количество объектов , которые де-сериализуются и, в свою очередь, управляют размером объекта. Я использую библиотеки Json.Net для этого.
Ниже приведен образец файла JSON, который я получаю в качестве потока в свое приложение.
{
"Locations": [{
"LocationId": "",
"ParentLocationId": "",
"DisplayFlag": "Y",
"DisplayOptions": "",
"DisplayName": "",
"Address": "",
"SecondaryAddress": "",
"City": "",
"State": "",
"PostalCode": "",
"Country": "",
"Latitude": 40.59485,
"Longitude": -73.96174,
"LatLonQuality": 99,
"BusinessLogoUrl": "",
"BusinessUrl": "",
"DisplayText": "",
"PhoneNumber": "",
"VenueGroup": 7,
"VenueType": 0,
"SubVenue": 0,
"IndoorFlag": "",
"OperatorDefined": "",
"AccessPoints": [{
"AccessPointId": "",
"MACAddress": "",
"DisplayFlag": "",
"DisplayOptions": "",
"Latitude": 40.59485,
"Longitude": -73.96174,
"Status": "Up",
"OperatorDefined": "",
"RoamingGroups": [{
"GroupName": ""
},
{
"GroupName": ""
}],
"Radios": [{
"RadioId": "",
"RadioFrequency": "",
"RadioProtocols": [{
"Protocol": ""
}],
"WifiConnections": [{
"BSSID": "",
"ServiceSets": [{
"SSID": "",
"SSID_Broadcasted": ""
}]
}]
}]
}]
},
{
"LocationId": "",
"ParentLocationId": "",
"DisplayFlag": "Y",
"DisplayOptions": "",
"DisplayName": "",
"Address": "",
"SecondaryAddress": "",
"City": "",
"State": "",
"PostalCode": "",
"Country": "",
"Latitude": 40.59485,
"Longitude": -73.96174,
"LatLonQuality": 99,
"BusinessLogoUrl": "",
"BusinessUrl": "",
"DisplayText": "",
"PhoneNumber": "",
"VenueGroup": 7,
"VenueType": 0,
"SubVenue": 0,
"IndoorFlag": "",
"OperatorDefined": "",
"AccessPoints": [{
"AccessPointId": "",
"MACAddress": "",
"DisplayFlag": "",
"DisplayOptions": "",
"Latitude": 40.59485,
"Longitude": -73.96174,
"Status": "Up",
"OperatorDefined": "",
"RoamingGroups": [{
"GroupName": ""
},
{
"GroupName": ""
}],
"Radios": [{
"RadioId": "",
"RadioFrequency": "",
"RadioProtocols": [{
"Protocol": ""
}],
"WifiConnections": [{
"BSSID": "",
"ServiceSets": [{
"SSID": "",
"SSID_Broadcasted": ""
}]
}]
}]
}]
}]
}
мне нужно, чтобы быть в состоянии вытащить отдельные объекты Места, так что я смотрел бы на следующий
{
"LocationId": "",
"ParentLocationId": "",
"DisplayFlag": "Y",
"DisplayOptions": "",
"DisplayName": "",
"Address": "",
"SecondaryAddress": "",
"City": "",
"State": "",
"PostalCode": "",
"Country": "",
"Latitude": 40.59485,
"Longitude": -73.96174,
"LatLonQuality": 99,
"BusinessLogoUrl": "",
"BusinessUrl": "",
"DisplayText": "",
"PhoneNumber": "",
"VenueGroup": 7,
"VenueType": 0,
"SubVenue": 0,
"IndoorFlag": "",
"OperatorDefined": "",
"AccessPoints": [{
"AccessPointId": "",
"MACAddress": "",
"DisplayFlag": "",
"DisplayOptions": "",
"Latitude": 40.59485,
"Longitude": -73.96174,
"Status": "Up",
"OperatorDefined": "",
"RoamingGroups": [{
"GroupName": ""
},
{
"GroupName": ""
}],
"Radios": [{
"RadioId": "",
"RadioFrequency": "",
"RadioProtocols": [{
"Protocol": ""
}],
"WifiConnections": [{
"BSSID": "",
"ServiceSets": [{
"SSID": "",
"SSID_Broadcasted": ""
}]
}]
}]
}]
}
Я пытаюсь использовать Json.NET JsonTextReader для достижения этой цели , однако я не могу заставить читателя содержать все место в своем буфере из-за размера записей в потоке, который первоначально читатель будет иметь до «RadioProtocols», который находится в середине пути через объект, к тому времени поток достигает конца объекта, читатель отбросил начало объекта.
код, я использую, чтобы попытаться получить эту функцию для работы
var ser = new JsonSerializer();
using (var reader = new JsonTextReader(new StreamReader(stream)))
{
reader.SupportMultipleContent = true;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject && reader.Depth == 2)
{
do
{
reader.Read();
} while (reader.TokenType != JsonToken.EndObject && reader.Depth == 2);
var singleLocation = ser.Deserialize<Locations>(reader);
}
}
}
Любая информация об этом или альтернатива делать это было бы весьма признателен. В качестве дополнительной заметки способ, которым наши клиенты отправляют информацию, в настоящее время не может измениться.
Это звучит, как вы собираетесь придется свернуть свой собственный сериалайзер, потому что маленький разумный блок, который json.NET JSON собирается десериализации заставит вас 'OutOfMemoryException'. При этом я считаю, что это совершенно неправильный подход. Я бы рассмотрел более серьезную проблему, которая является вашим явно вашим громоздким источником данных или недостаточным оборудованием. – evanmcdonnal
К сожалению, мы не можем изменить подход в это время, нам в основном сказали исправлять только или, точнее, «просто заставить его работать, не меняя слишком много». – polydegmon
Я попытался запустить ваш код, но я нашел проблему. Предполагая, что тип «Locations» соответствует записи в массиве «Locations», код генерирует исключение, потому что читатель неправильно расположен в свойстве «LocationId». Является ли идея перечислить каждую запись в массиве 'Locations', загружая каждый из них отдельно? – dbc