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

第十五章 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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容