1. 程式人生 > 其它 >第十五章 Caché 變數大全 $STORAGE 變數

第十五章 Caché 變數大全 $STORAGE 變數

技術標籤:Caché 變數大全CachéCachestorage記憶體變數位元組數

文章目錄

第十五章 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