기계에서 반환 한 데이터를 처리하고 있습니다. 대형 농장에서 일반적으로 사용되는 기계로 각기 다른 깊이의 데이터를 수집하고 다른 장치를 사용합니다.거대한 데이터가있는 중첩 된 foreach 메모리 부족 예외가 발생했습니다.
각 농장 70-100 필드를 포함 할 수 있으며, 각 필드는 약 10 백만 데이터
저는 여기에 각각의 데이터를 처리 및 클라이언트 요구 사항에 따라 몇 가지 계산을 적용 할 필요가
가 포함되어 있습니다.팜을 먼저 반복 한 다음 팜의 필드를 작성한 다음 각 팜에 사용되는 장치를 만들고 각 장치의 깊이를 기준으로 기록해야합니다. 그래서 마침내 나는 약 10 억 반복을하고 싶습니다. 내 코드
public async void MigrateData()
{
masterData = await CatalogService.ExportMasterData(AppDataModel.Catalog, this.UserId);
foreach (var fieldItem in masterData.Fields)
{
var fieldReferenceId = fieldItem.ReferenceId;
dynamic loggedData = AppDataModel.Documents.LoggedData.Where(data => data.FieldId == fieldReferenceId);
dynamic fieldDbMappingData = fieldItem;
foreach (var data in loggedData)
{
yieldMaster.OperationalLogModalResponse = await YieldDataMigrationService.AddOperationalLogs("loggedDataDescription");
yieldMaster.OperationalLogDataModelResponse = await YieldDataMigrationService.AddOperationalLogData(fieldDbMappingData, yieldMaster.OperationalLogModalResponse);
FetchContentData(data);
}
}
}
private async void FetchContentData(LoggedData data)
{
foreach (var opdata in data.OperationData)
{
var filteredList = AggregateDataBasedOnFilter(opdata);
int count = filteredList.Count;
totalRecordCount += count;
for (int i = 1; i <= count; i = i + 1000)
{
var response = await YieldDataMigrationService.AddYiledData(filteredList.GetRange(i, i + 1000 >= count ? count - i : 1000));
}
}
//Filter data based on timestamp values , get the first data in 5 seconds interval
System.GC.Collect();
}
private dynamic AggregateDataBasedOnFilter(OperationData opdata)
{
List<dynamic> listSpacialRecords = new List<dynamic>();
IEnumerable<SpatialRecord> spacialRecords = opdata.GetSpatialRecords();
spacialRecords = GetAggregateBasedOnTimeStamb(spacialRecords);
Nullable<Guid> productid;
for (int depth = 0; depth <= opdata.MaxDepth; depth++)
{
IEnumerable<DeviceElementUse> deviceElementUses = opdata.GetDeviceElementUses(depth);
StevProduct productDbMappingData = masterData.Products.Where(product => product.ReferenceId == opdata.ProductId).FirstOrDefault();
if (productDbMappingData == null)
{
productid = null;
}
else
{
productid = productDbMappingData.Id;
}
foreach (var deviceElement in deviceElementUses)
{
List<dynamic> dvList = new List<dynamic>();
IEnumerable<WorkingData> workingData = deviceElement.GetWorkingDatas();
//foreach (var spacerecord in spacialRecords)
Parallel.ForEach(spacialRecords, (spacerecord) =>
{
List<MeterValue> dat = new List<MeterValue>();
var latitude = ((AgGateway.ADAPT.ApplicationDataModel.Shapes.Point)spacerecord.Geometry).Y;
var longitude = ((AgGateway.ADAPT.ApplicationDataModel.Shapes.Point)spacerecord.Geometry).X;
var timeStamp = spacerecord.Timestamp;
//Parallel.ForEach(workingData, (wdItem) =>
foreach (var wdItem in workingData)
{
RepresentationValue spaceMeteredValue = spacerecord.GetMeterValue(wdItem);
if (spaceMeteredValue != null && wdItem.Representation != null)
{
//row[wdItem.Representation.Code] = meteredValue.Value.Value;
var objMeterValue = new MeterValue();
objMeterValue.key = wdItem.Representation.Code;
objMeterValue.value = spaceMeteredValue.Designator != null ? Convert.ToString(spaceMeteredValue.Designator) : "";
dat.Add(objMeterValue);
}
}
var newSpacialvalue = new
{
operationLogDataId = yieldMaster.OperationalLogDataModelResponse.Id,
order = deviceElement.Order,
totalDistanceTravelled = deviceElement.TotalDistanceTravelled,
totalElapsedTime = deviceElement.TotalElapsedTime,
uploadedOn = DateTime.Now.ToUniversalTime(),
collectedOn = timeStamp.ToUniversalTime(),
cropId = "8296e610-c055-11e7-851e-ad7650a5f99c",
productId = productid,
latitude = latitude,
longitude = longitude,
deviceConfigurationId = deviceElement.DeviceConfigurationId,
operationDataId = deviceElement.OperationDataId,
spatialRecords = dat,
depth = depth,
timeStamp = timeStamp,
totaldata = totalRecordCount
};
lock (listSpacialRecords)
{
listSpacialRecords.Add(newSpacialvalue);
}
});
}
}
listSpacialRecords = listSpacialRecords
.Skip(1)
.Aggregate(
listSpacialRecords.Take(1).ToList(),
(a, x) =>
{
if (x.timeStamp.Subtract(a.Last().timeStamp).TotalSeconds >= 10.0)
{
a.Add(x);
}
return a;
});
GC.Collect();
return listSpacialRecords;
}
내 실제 시나리오는 이것보다 더 복잡 아래처럼 보인다. 그것에는 foreach
과 계산이 많이 있습니다. 전반적인 프로세스가 30 분 이상 실행됩니다. 그러나 그 사이에 나는 메모리가 없어지고있다. 예외. 이 거대한 데이터를 다루는 방법에 대해서는 전혀 모른다.
누구나 중첩 된 foreach보다 더 나은 접근 방법이 있습니까 ?? 또는 메모리 부족을 피하는 솔루션?
참고 : 각 기능을 별도의 기능으로 이동했지만 여전히 메모리 오류가 표시되었습니다. 또한 논리 섹션에 의해 계산 된 데이터를 처리하는 로컬 목록이 있습니다. 지역 목록 세계적인 객체가 아니다
걸릴 및 처리 배치 건너 뛰기? –
왜 foreach (FieldData의 var 필드)를 세 번 ** 호출합니까? – stuartd
@stuartd 미안하지만 오타였습니다. 편집 됨 –