MT5 EA内存溢出排查实战:日志分析与资源监控优化指南(0925)
MT5 EA内存溢出排查实战:日志分析与资源监控优化指南(0925)
上个月我挂在一个小VPS上的多品种EA突然开始报错,MT5终端日志刷得飞快,不到十分钟内存占用从几百MB飙到1.8G,最后直接卡死。重启后跑了两小时又复现。那台VPS只跑了三个货币对加一个黄金,按理说不该这么吃资源。排查了一圈,问题出在我自己写的指标缓冲区没做释放,加上历史订单遍历函数在每次Tick里都全量扫描。这个坑我想不少人都踩过,今天就把整个排查链路和优化手段拆开讲讲。

先看日志,别急着改代码
EA内存异常时,MT5的「专家」和「日志」两个标签页信息量完全不同。专家页只记录Print和报错信息,日志页会记录终端级的资源警告。我那次就是在日志里看到反复出现的「not enough memory」和「array out of range」,才锁定方向。
具体路径:MT5菜单栏 → 查看 → 日志 → 右键导出为CSV。重点筛三类关键词:memory、array、timeout。如果EA里自己写了内存打印,比如每1000个Tick输出一次 TerminalInfoInteger(TERMINAL_MEMORY_USAGE),排查效率会高很多。
注意:很多人的EA在OnTick里用Print调试,跑实盘时忘了删,日志文件本身就会吃掉几百MB磁盘和内存缓存。这个低级错误我见过不止一次。
资源监控:别只盯着任务管理器
Windows任务管理器看到的是整个terminal64.exe的占用,分不清是EA、指标还是图表对象吃掉的。更细的粒度要靠MT5自带工具和外部脚本。
- MT5内置:工具 → 选项 → 图表 → 勾选「显示最大内存消耗」不现实,实际用的是「交易」标签页里的EA性能统计。
- 外部脚本:用Python的psutil定时采样terminal64.exe的Working Set和Private Bytes,每5秒写入CSV。我一般跑24小时,看曲线拐点。
- MQL5侧:在OnTimer里调用
GetTickCount64()和TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)做粗粒度监控。
关键指标是Private Bytes的持续上升趋势。如果每次OnTick后都涨一点、从不回落,基本可以判定是内存泄漏,而不是正常波动。
三个最常见的泄漏源头
第一个是动态数组和字符串拼接。MQL5里字符串是不可变的,每次 str += "xxx" 都会新建对象。在OnTick里高频拼接日志字符串,内存涨得比想象中快。改成固定长度字符数组或只在必要时输出。
第二个是指标句柄未释放。用 iCustom() 或 iMA() 创建的句柄,如果EA反复初始化(比如参数变更后重新加载),旧句柄不会自动回收。正确做法是在OnDeinit里对每个句柄调用 IndicatorRelease()。
第三个是历史订单遍历。下面这段伪代码是典型反例:
for(int i=0; i<OrdersTotal(); i++){
if(OrderSelect(i, SELECT_BY_POS)){
// 每次都全量检查历史
}
}
优化方式是先用 HistorySelect(startTime, TimeCurrent()) 限定时间窗口,再用缓存机制记录上次处理到的订单号。我在一个网格EA上做这个改动后,单次OnTick耗时从12ms降到1.8ms,内存增长曲线也平了。
优化前后的回测对比
拿我那个出问题的多品种EA举例,参数配置如下:
- 品种:EURUSD、GBPUSD、XAUUSD
- 时间周期:M15
- 初始资金:10000
- 回测区间:2023.01–2024.06
- 建模质量:99.9%
优化前:胜率41.2%,盈利因子0.83,最大回撤28.7%,内存峰值1.6G。优化后(释放句柄+缓存订单+去掉Tick内字符串拼接):胜率43.5%,盈利因子1.21,最大回撤19.4%,内存峰值稳定在420MB左右。胜率提升不大,但盈利因子和回撤改善明显,说明之前的内存抖动确实影响了订单执行逻辑。
注意:回测时MT5默认只用一个CPU核心,内存表现和实盘多线程环境有差异。建议用「每笔订单」模式跑一遍,再和「仅开盘价」模式对比,看内存曲线是否一致。
部署时的几个实操细节
VPS选型上,2核4G跑三到五个EA是舒适区,但前提是每个EA的内存峰值控制在300MB以内。如果EA里用了大量历史数据缓存,建议上4核8G。我目前在用的是一台4核8G的Windows Server 2022,开了六个MT5实例,每个实例独立数据目录,互不干扰。
部署步骤:先在本地MT5用策略测试器跑24小时压力测试,确认内存曲线平稳;然后把EA和依赖的指标文件一起复制到VPS的MQL5/Experts和MQL5/Indicators目录;重启终端后检查日志有无「cannot load indicator」报错。常见错误是忘记复制自定义指标,EA加载后句柄返回INVALID_HANDLE,后续所有计算全部失效。
另外提醒一点:MT5的「最大柱形图」设置(工具 → 选项 → 图表)默认是无限,改成5000到10000根能显著降低内存占用。这个参数在跑多品种时效果尤其明显。
核心建议就一句:每次改完EA代码,先看OnDeinit里有没有释放所有动态资源,再谈策略逻辑。
免责声明:本文仅代表作者观点,不构成任何投资建议。市场有风险,交易需谨慎。
