【发布时间】:2021-02-18 02:33:55
【问题描述】:
要求如下:
我们有一个第三方客户端,我们需要从那里获取数据并存储在数据库中(最终)。
客户端与我们共享数据的方式是通过 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 笔交易需要我们调用这些方法,并且数据会存储在文件中。
实现此功能的方式是使用具有主子关系的并行编程,如下所示:
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 Data Deal v2.0.exe 是子代码,将执行 5000 次,因为 deallist 包含 5000 个交易。
CMBS Intex Data Deal v2.0.exe 代码包含调用 dll 并将数据存储在上述文件中的代码。
面临的问题:
- 代码运行时将主代码和子代码保持在一个位置,但在 3000 次交易后出现内存不足异常。[对于 32 GB RAM,处理器计数 =16]
- 上面的代码(Master-Child)也占用了很多内存,它在一小时内运行到 4800 个交易(内存使用在 4800 个交易左右逐渐达到 100%),然后对于剩余的 200 个交易它需要将近 1 小时(因此,总共需要 2 小时)。[对于 32 GB RAM,处理器数量 =16] 尝试使用 Master child 的原因是假设 GC 将负责 Child 中所有对象的内存处理。
数据存储在文本文件中后,运行 perl 脚本并将数据加载到数据库中。
尝试的方法:
我没有将数据保存在文本文件中然后存储到数据库中,而是尝试将数据直接存储到数据库中而不将它们放入文件中(假设 I/O 操作消耗大量内存),但这也没有每次数据库崩溃/挂起时工作。
注意:
- 与 DLL 相关的所有句柄都已正确关闭。
- 对 DLL 方法的调用会消耗大量内存,但我们无法控制它,因此无法减少它。
- 使用 Parallel 方法的原因是,如果我们使用顺序方法,获取和加载数据需要很多小时,并且我们需要每天运行两次,因为数据不断变化,所以需要跟上-date 来自客户的最新数据。
- 还有一个 CPU 最大化问题,但已通过保持 MaxDegreeOfParallelism = System.Environment.ProcessorCount 得到解决。
问题:
有没有办法减少流程完成所花费的时间。 目前需要 2 小时才能完成,但这可能是由于达到 4800 笔交易时没有剩余内存,并且没有任何内存,它无法进一步处理。 有没有办法通过尝试不同的方式来执行此操作来减少内存消耗,或者如果在同一代码中进行更改可以使其工作?
【问题讨论】:
标签: performance memory-management out-of-memory task-parallel-library parallel.foreach