2017-12-18 21 views
0

기계에서 반환 한 데이터를 처리하고 있습니다. 대형 농장에서 일반적으로 사용되는 기계로 각기 다른 깊이의 데이터를 수집하고 다른 장치를 사용합니다.거대한 데이터가있는 중첩 된 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보다 더 나은 접근 방법이 있습니까 ?? 또는 메모리 부족을 피하는 솔루션?

참고 : 각 기능을 별도의 기능으로 이동했지만 여전히 메모리 오류가 표시되었습니다. 또한 논리 섹션에 의해 계산 된 데이터를 처리하는 로컬 목록이 있습니다. 지역 목록 세계적인 객체가 아니다

+0

걸릴 및 처리 배치 건너 뛰기? –

+0

왜 foreach (FieldData의 var 필드)를 세 번 ** 호출합니까? – stuartd

+0

@stuartd 미안하지만 오타였습니다. 편집 됨 –

답변

0

푸 네엣은 "커다란 세트를 반복하고 있지만 쓰레기 제거가 빠르지 않은 임시 변수에 데이터를 저장할 수 있기 때문에 OutOfMemory가 발생하지 않습니다. 일부 수표를 설정 한 후에 명시 적 가비지 수집을 수행해야한다고 생각합니다. "

필요없는 경우 수동으로 요소를 배치하면 더 좋을 것입니다.

{object}.Dispose(); 

또는 모든 루프의 끝에 가비지 수집 명령문을 넣으십시오.

GC.Collect(); 

또한 조작이 직렬/cumul 조작이 아닌 경우 더 나은 성능을 위해 Parallel.Foreach를 사용할 수 있습니다.

+0

GC.Collect()가 있습니다. 하지만 여전히 문제가 있습니다. –

+0

@ArunprasanthKV 그런 다음 필요하지 않은만큼 만든 객체/캐싱을 수동으로 처리해야합니다. –