计算资源:内存、磁盘和 CPU

与所有程序一样,MQL 应用程序也会消耗计算机资源,包括内存、磁盘以及 CPU。鉴于终端本身是资源密集型的(尤其因为可能下载具有长期历史记录的多个金融工具的报价和分时报价),有时候就需要从可用资源限制的接近程度角度分析和控制情况。

MQL5 API 提供了若干属性,允许你估计最大可用资源以及已使用的资源。这些特性汇总在 ENUM_MQL_INFO_INTEGER 和 ENUM_TERMINAL_INFO_INTEGER 枚举中。

标识符

说明

MQL_MEMORY_LIMIT

用于 MQL 程序的最大可能动态内存数(单位 KB)

MQL_MEMORY_USED

MQL 程序使用的内存(单位 MB)

MQL_HANDLES_USED

类对象数量

TERMINAL_MEMORY_PHYSICAL

系统中的物理 RAM(单位 MB)

TERMINAL_MEMORY_TOTAL

终端(代理)进程可用的内存(物理内存+交换文件,即虚拟内存)(单位 MB)

TERMINAL_MEMORY_AVAILABLE

终端(代理)进程的空闲内存(单位 MB),TOTAL 的一部分

TERMINAL_MEMORY_USED

终端(代理)使用的内存(单位 MB),TOTAL 的一部分

TERMINAL_DISK_SPACE

空闲磁盘,考虑终端(代理)的 MQL5/Files 文件夹的配额(单位 MB)

TERMINAL_CPU_CORES

系统中的处理器核心数

TERMINAL_OPENCL_SUPPORT

支持的 OpenCL 版本,表示为 0x00010002 = 1.2;"0" 表示不支持 OpenCL

MQL 程序可用的最大内存由 MQL_MEMORY_LIMIT 特性描述。这是列出的特性中唯一使用千字节数 (KB) 作为单位的。所有其它特性均以兆字节数 (MB) 返回。原则上,MQL_MEMORY_LIMIT 等于 TERMINAL_MEMORY_TOTAL,即默认情况下计算机上的所有可用内存可分配给一个 MQL 程序。然而,终端(尤其是其用于 MetaTrader VPS 的云实施)以及云测试代理可能会限制单个 MQL 程序使用的内存。这样 MQL_MEMORY_LIMIT 将大大少于 TERMINAL_MEMORY_TOTAL。

由于 Windows 通常创建一个等于物理内存 (RAM) 大小的交换文件, 因此 TERMINAL_MEMORY_TOTAL 特性大小最多可能是 TERMINAL_MEMORY_PHYSICAL 的两倍。

所有可用虚拟内存 TERMINAL_MEMORY_TOTAL 分为已使用 (TERMINAL_MEMORY_USED) 内存和仍空闲 (TERMINAL_MEMORY_AVAILABLE) 内存。

本书提供了 EnvProvision.mq5 脚本,该脚本将所有指定特性记录到日志。

void OnStart()
{
   PRTF(MQLInfoInteger(MQL_MEMORY_LIMIT)); // Kb!
   PRTF(MQLInfoInteger(MQL_MEMORY_USED));
   PRTF(TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL));
   PRTF(TerminalInfoInteger(TERMINAL_MEMORY_TOTAL));
   PRTF(TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE));
   PRTF(TerminalInfoInteger(TERMINAL_MEMORY_USED));
   PRTF(TerminalInfoInteger(TERMINAL_DISK_SPACE));
   PRTF(TerminalInfoInteger(TERMINAL_CPU_CORES));
   PRTF(TerminalInfoInteger(TERMINAL_OPENCL_SUPPORT));
   
   uchar array[];
   PRTF(ArrayResize(array1024 * 1024 * 10)); // allocate 10 Mb
   PRTF(MQLInfoInteger(MQL_MEMORY_USED));
   PRTF(TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE));
   PRTF(TerminalInfoInteger(TERMINAL_MEMORY_USED));
}

首次输出特性后,我们为数组分配 10 MB,然后再次检查内存。结果示例如下所示(你将有自己的值)。

MQLInfoInteger(MQL_MEMORY_LIMIT)=8388608 / ok
MQLInfoInteger(MQL_MEMORY_USED)=1 / ok
TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)=4095 / ok
TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)=8190 / ok
TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)=7842 / ok
TerminalInfoInteger(TERMINAL_MEMORY_USED)=348 / ok
TerminalInfoInteger(TERMINAL_DISK_SPACE)=4528 / ok
TerminalInfoInteger(TERMINAL_CPU_CORES)=4 / ok
TerminalInfoInteger(TERMINAL_OPENCL_SUPPORT)=0 / ok
ArrayResize(array,1024*1024*10)=10485760 / ok
MQLInfoInteger(MQL_MEMORY_USED)=11 / ok
TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)=7837 / ok
TerminalInfoInteger(TERMINAL_MEMORY_USED)=353 / ok

注意总虚拟内存 (8190) 是物理内存的 (4095) 的两倍。脚本可用的内存数是 8388608 KB,几乎等于全部内存 8190 MB。空闲 (7842) 和已使用 (348) 系统内存总和也等于 8190。

如果在为数组分配内存之前,MQL 程序占用 1 Mb,则分配之后,其已经占用 11 Mb。同时,终端占用的内存数仅增加了 5 MB(从 348 增加到 353),因为一些资源已事先预留。