zl程序教程

您现在的位置是:首页 >  后端

当前栏目

第十五章 Caché 变量大全 $STORAGE 变量

变量 大全 Storage Cach 第十五章
2023-09-11 14:15:37 时间

文章目录

第十五章 Caché 变量大全 $STORAGE 变量

包含可用于局部变量存储的字节数。

大纲

$STORAGE
$S

描述

$STORAGE返回可用于当前进程分区中的本地变量存储的字节数。 $STORAGE的初始值由$ZSTORAGE的值确定,该值是该进程可用的最大内存量。 $ZSTORAGE值(以千字节为单位)越大,$STORAGE值(以字节为单位)越大。但是,$ZSTORAGE$STORAGE之间的关系不是简单的1:1比率。

$STORAGE值受以下操作影响:

  • 在局部变量空间中定义局部变量(例如,使用set命令)时,$STORAGE会减少。$STORAGE的减少对应于存储局部变量的值所需的空间量;局部变量名称的大小对$STORAGE没有影响,但下标级别的数量确实会影响$STORAGE$STORAGE值随着删除局部变量(例如,通过使用kill命令)而增加。
  • 发出NEW命令时,$STORAGE会减少。NEW建立一个新的执行级别;在上一个执行级别为局部变量(无论是否使用)预留的空间在新的执行级别上不可用。最初的new项目减少了大约15000的$STORAGE;后续的每个new项目减少了12288的$STORAGE。发出QUIT命令退出执行级别时,$STORAGE值会增加。
  • 当定义控制流语句(如IFFOR)或块结构(如TRYCATCH)时,$STORAGE会减少。分配存储是用来编译这些结构的,而不是用来执行它们的。因此,无论是否循环或循环多少次,For语句都会消耗相同的存储量;无论执行多少分支,每个IfELSEIFELSE子句都会消耗一定数量的存储。空间是从编译代码的进程分配的。请注意,for循环通常将局部变量定义为计数器。

$STORAGE值不受设置进程私有全局变量、全局变量或特殊变量的影响。$STORAGE值不受更改名称空间的影响。启用长字符串不会影响$STORAGE值,因为在进程分区中没有分配长字符串存储。

不能使用SET命令修改$STORAGE特殊变量。尝试这样做会导致<SYNTAX>错误。

内存不足和<store>错误

$STORAGE值可以是正数,也可以是负数。值为零并不表示没有可用存储,但表示存储极度短缺。如果$STORAGE减少到小于零,则会在某个时刻发生<store>错误。例如,如果$STORAGE减少到-7000,则为另一个局部变量分配存储可能会由于<store>错误而失败,这表明没有足够的可用存储空间来存储局部变量值或建立新的执行级别。

第一个<store>错误发生在$STORAGE的某个值小于零时;确切的负$STORAGE值阈值取决于上下文。此<store>错误指示必须通过增加$ZSTORAGE或通过KILLQUIT操作释放一些已分配的存储来获得额外的存储。当第一个<store>错误发生时,Caché会自动为进程提供1MB的额外内存,以启用错误处理和恢复。Caché不会更改$ZSTORAGE;它允许$STORAGE进一步进入负数值。

当第一个<store>错误发生时,Caché在内部将进程指定为内存不足状态。而在此低内存状态下,该进程可以继续分配内存,并且$STORAGE的值可以继续减少到更低的负数。在此低内存状态下,进程可能会释放一些已分配的内存,从而导致$STORAGE的值上升。因此,$STORAGE的值可以在一个值范围内上升或下降,而不会发出额外的<store>错误。此外,在第一个<store>错误之后,可能会看到由于Caché释放了一些内部内存而导致$STORAGE的小幅上升。

第一个<store>错误提供了一些内存缓冲,允许进程调用诊断、执行磁盘保存、正常退出、释放内存并继续。

进程保持低内存状态,直到发生以下任何一种情况:

  • 该过程提供了足够的内存。进程可以通过增加$ZSTORAGE分配和/或通过KILLQUIT操作释放分配的存储来实现这一点。当$STORAGE的值超过256K(或$ZSTORAGE的25%,以较小者为准)时,Caché将进程从低内存状态移除。此时,如果可用内存减少到负数,该进程可能会再次发出<store>错误。
  • 该进程会消耗额外的内存。当$STORAGE的值达到-1048576时,会出现第二个<STORE>错误。如果进程到达这一点,则没有更多的内存可供该进程使用,并且进一步的进程操作将变得不可预测。这一过程很可能会立即终止。

可以通过调用$SYSTEM.Process.MemoryAutoExpanStatus()方法来确定<store>错误的原因。

示例

以下示例显示当$ZSTORAGE设置为较小的值时,$STORAGE如何变小。请注意,这两个值之间的关系(比率)是可变的:

/// d ##class(PHA.TEST.SpecialVariables).STORAGE()
ClassMethod STORAGE()
{
	SET $ZS=262144
	FOR i=1:1:10 {
		WRITE "$ZS=",$ZS," $S=",$S," ratio=",$NORMALIZE($S/$ZS,3),!
		IF $ZS>30000 {SET $ZS=$ZS-30000 }
	}
}

以下示例显示了在分配局部变量时$STORAGE如何减少,而在终止局部变量时$STORAGE如何增加:

/// d ##class(PHA.TEST.SpecialVariables).STORAGE1()
ClassMethod STORAGE1()
{
	WRITE "$STORAGE=",$S," initial value",!
	FOR i=1:1:30 {
		SET a(i)="abcdefghijklmnopqrstuvwxyz"
		WRITE "$STORAGE=",$S,! 
	}
	KILL a
	WRITE !,"$STORAGE=",$S," after KILL",!
}
DHC-APP>d ##class(PHA.TEST.SpecialVariables).STORAGE1()
$STORAGE=22551864 initial value
$STORAGE=22551728
$STORAGE=22551664
$STORAGE=22551408
$STORAGE=22551344
$STORAGE=22551280
$STORAGE=22551216
$STORAGE=22551152
$STORAGE=22551088
$STORAGE=22551024
$STORAGE=22550960
$STORAGE=22550896
$STORAGE=22550832
$STORAGE=22550768
$STORAGE=22550704
$STORAGE=22550640
$STORAGE=22550320
$STORAGE=22550256
$STORAGE=22550192
$STORAGE=22550128
$STORAGE=22550064
$STORAGE=22550000
$STORAGE=22549936
$STORAGE=22549872
$STORAGE=22549808
$STORAGE=22549744
$STORAGE=22549680
$STORAGE=22549616
$STORAGE=22549552
$STORAGE=22549488
$STORAGE=22549424
 
$STORAGE=22551856 after KILL

以下示例显示分配的局部变量的下标级别数如何影响$STORAGE

/// d ##class(PHA.TEST.SpecialVariables).STORAGE2()
ClassMethod STORAGE2()
{
	WRITE "无下标:",!
	SET before=$S
	SET a="abcdefghijklmnopqrstuvwxyz"
	WRITE " 分配的内存 ",before-$S,!
	KILL a
	WRITE "1个下标级别:",!
	SET before=$S
	SET a(1)="abcdefghijklmnopqrstuvwxyz"
	WRITE " 分配的内存 ",before-$S,!
	KILL a(1)
	WRITE "9个下标级别:",!
	SET before=$S
	SET a(1,2,3,4,5,6,7,8,9)="abcdefghijklmnopqrstuvwxyz"
	WRITE " 分配的内存 ",before-$S,!
	KILL a(1,2,3,4,5,6,7,8,9)
}
DHC-APP>d ##class(PHA.TEST.SpecialVariables).STORAGE2()
无下标:
 分配的内存 80
1个下标级别:
 分配的内存 128
9个下标级别:
 分配的内存 640

以下示例显示了当NEW建立新的执行级别时,$STORAGE如何减少(在该级别变得不可用):

/// d ##class(PHA.TEST.SpecialVariables).STORAGE3()
ClassMethod STORAGE3()
{
	WRITE "不断增加的级别:",!
	FOR i=1:1:10 {
		WRITE "$STORAGE=",$S,! NEW 
	}
}
DHC-APP>d ##class(PHA.TEST.SpecialVariables).STORAGE3()
不断增加的级别:
$STORAGE=22550456
$STORAGE=22536704
$STORAGE=22524416
$STORAGE=22512128
$STORAGE=22499840
$STORAGE=22487552
$STORAGE=22475264
$STORAGE=22462976
$STORAGE=22450688
$STORAGE=22438400

下面的示例显示了$STORAGE如何随着局部变量的赋值而减少,直到它进入内存不足状态,并发出<store>错误。<store>错误由Catch块捕获,该块调用StoreErrorReason()方法来确定导致错误的原因。请注意,进入CATCH块会消耗大量存储空间。一旦进入CATCH块,此示例将再分配一个变量。

/// d ##class(PHA.TEST.SpecialVariables).STORAGE4()
ClassMethod STORAGE4()
{
	TRY {
		WRITE !,"TRY 块",!
		SET init=$ZSTORAGE
		SET $ZSTORAGE=456
		WRITE "初始化 $STORAGE=",$STORAGE,!
		FOR i=1:1:10000 {
			SET pre=$STORAGE
			SET var(i)="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
			IF $STORAGE<0 {
				WRITE "var(",i,")  负内存=",$STORAGE,! 
			} ELSEIF pre<$STORAGE {
				WRITE "var(",i,") 新分配 $S=",$STORAGE,! 
			} ELSE {
				WRITE "var(",i,") $S=",$STORAGE,! 
			}
		}
	}
	CATCH myexp {
		WRITE !,"CATCH 块异常处理",!!
		WRITE "Name: ",$ZCVT(myexp.Name,"O","HTML"),!
		IF myexp.Name="<STORE>" {
			WRITE "内存错误原因=",
			$SYSTEM.Process.StoreErrorReason(),! 
		}
		WRITE "$S=",$STORAGE,!
		SET j=i
		SET var(j)="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
		WRITE "var(",j,") 增加了一个变量 $S=",$STORAGE,!
		SET $ZSTORAGE=init
		RETURN
	}
}
...
var(2039) $S=48152
var(2040) $S=48024
var(2041) $S=47896
var(2042) $S=47768
var(2043) $S=47640
var(2044) $S=47512
var(2045) $S=47384
var(2046) $S=47256
var(2047) $S=47128
 
CATCH 块异常处理
 
Name: &lt;STORE&gt;
内存错误原因=1
$S=39240
var(2048) 增加了一个变量 $S=6336