使用并行编程存储数据

问题描述

要求如下:

我们有一个第三方客户,我们需要从那里获取数据并最终存储在数据库中。

客户端与我们共享数据的方式是通过dll的函数(该dll由C ++代码构建),我们需要使用适当的参数调用这些函数,然后得到结果。

Declare Function wcmo_deal Lib "E:\IGB\System\Intex\vcmowrap\vcmowr64.dll" (
    ByRef WCMOarg_Handle As String,ByRef WCMOarg_User As String,ByRef WCMOarg_Options As String,ByRef WCMOarg_Deal As String,ByRef WCMOarg_DataOut As String,ByRef WCMOarg_ErrOut As String) _
     As Long

wcmo_deal(wcmo_deal_WCMOarg_Handle,WCMOarg_User,WCMOarg_Options,WCMOarg_Deal,WCMOarg_DataOut,WCMOarg_ErrOut)

这里WCMOarg_DataOut是我们获取的数据,需要存储。

与上述方法类似,我们还有10种方法(总共11种方法提取数据,并使用以下方法将数据(每个字符串约500 KB至1 MB)存储在文件中:>

File.WriteallText(logPath & sDealName & ".txt",sDealName & " - " & WCMOarg_ErrOut & vbCrLf)

现在,这些方法调用针对每个交易运行。因此,只需一笔交易,我们就可以在11个不同的文件夹中输出文本文件,并与从客户端接收的数据一起存储。

我们总共需要调用5000个交易,这些数据需要存储在文件中。

实现此功能的方式是通过使用具有Master-Child关系的并行编程,如下所示:

Dim opts As New ParallelOptions
opts.MaxDegreeOfParallelism = System.Environment.ProcessorCount
Parallel.ForEach(dealList,opts,Sub(deal)
                                                 If Len(deal) > 0 Then
                                                     Dim dealPass As String = ""
                                                     Try
                                                         If dealPassDict.ContainsKey(deal.toupper) Then
                                                             dealPass = dealPassDict(deal.toupper)
                                                         End If
                                                         Dim p As New Process()
                                                         p.StartInfo.FileName = "E:\IGB_New\CMBS Intex Data Deal v2.0.exe"
                                                         p.StartInfo.Arguments = deal & "|" & keycode & "|" & dealPass & "|" & clArgs(1) & "|"
                                                         p.StartInfo.UseShellExecute = False
                                                         p.StartInfo.CreateNowindow = True
                                                         p.Start()
                                                         p.WaitForExit()
                                                     Catch ex As Exception
                                                         exceptions.Enqueue(ex)                                                             
                                                     End Try
                                                 End If
                                             End Sub)

其中 CMBS Intex数据交易v2.0.exe 是子代码,由于交易列表包含5000个交易,该代码将执行5000次。

CMBS Intex数据交易v2.0.exe代码包含调用dll并将数据存储在上述文件中的代码

面临的问题:

  1. 代码已运行,将主代码和子代码保持在一个地方,但是在3000次交易之后我们就出现了内存不足的情况。[对于32 GB RAM,处理器数= 16]
  2. 上面的代码(Master-Child)也占用了大量内存,它在一小时内可以运行多达4800笔交易(内存使用率在4800笔交易时逐渐达到100%),然后针对其余200笔交易需要近1个小时(因此,总共需要2个小时)。[对于32 GB RAM,处理器数= 16] 尝试使用Master child的原因是基于这样的假设,即GC将负责处理Child中所有对象的内存处理。

将数据存储在文本文件中之后,将运行一个perl脚本并将数据加载到数据库中。

尝试的方法

我没有将数据保留在文本文件中然后存储到数据库中,而是尝试将数据直接存储到DB中而不将它们放入文件中(假设I / O操作会消耗大量内存),但是这样做也没有每次DB崩溃/挂起时都会工作。

注意:

  1. 与DLL相关的所有句柄均已正确关闭
  2. 对DLL方法调用会占用大量内存,但是由于无法控制它,因此无法减少它。
  3. 使用并行方法的原因是,如果我们采用顺序方法,则将花费许多小时来获取和加载数据,并且由于数据不断变化,我们需要每天运行两次,因此需要及时更新。 -从客户端获取最新数据。
  4. 也存在cpu最大化问题,但已通过保留MaxDegreeOfParallelism = System.Environment.ProcessorCount来解决

问题:

有没有一种方法可以减少过程完成所花费的时间。 目前需要2个小时才能完成,但这可能是由于在达到4800个交易时没有剩余的内存,并且没有任何内存就无法进一步处理。 有没有办法尝试不同的执行方式来减少内存消耗,或者如果在相同的代码中进行更改可以使其正常工作,那是否有办法?

解决方法

平行主义很可能完全没有用。您受IO约束,而不是受CPU约束。 IO是瓶颈,而并行化甚至会使情况变得更糟。您可以尝试使用RAM drive,然后将所有输出复制到实际存储中。