Excellent, just excellent. It did find correctly all globals in a routine (no indirection). I populated in = ##class(%Stream.TmpCharacter).%New() with this code:
NumLines=^ROUTINE(routineName,0,0)   ; Omit extension
n=0:1:NumLines {
    S line=$T(@routineName+n^@routineName)
    D in.Write(line),in.Write($c(13,10))
}
in.Rewind()

I also added this after your Write:
                Set line=$G(^ROUTINE(rtnName,0,lineNum+1))
                Write $C(9),$E(line,token.p+1,token.p+token.c),!

I did not try finding globals in classes, but I assume this would be very similar. Is there any online documentation that shows that token value for globals is 18? Would be curious about other token values.

I rebuild ^rINDEX using, as recommended, D ##class(%Library.RoutineIndex).RebuildIndex($NAMESPACE). That reduced the number of ^rINDEX entries with an empty Date Modified, the cause of the $RO error. However, this function is partially based on ^ROUTINE which in its turn had bogus entries, all of the type ^ROUTINE("ABC",0,"SIZE")=<some integer>. That’s all these routines contain. I killed these ^ROUTINE nodes and rebuilt ^rINDEX. No empty Date Modified. 

I wrote a simple function to find non-printable characters in a routine:

findNonAscii
stream = ##class(%FileCharacterStream).%New()
stream.Filename="C:\TestAGbackup_2024-04-15_AG.txt"
f  {
        q:stream.AtEnd
        s line = stream.ReadLine()
        ; Strip all control characters, including non-processable by XML export, except for tabs and newlines
        s l2=$ZSTRIP(line,"*C","",$C(9)_$C(10)_$C(13))
        w:l2'=line line,!,l2,!
}
q

Everybody, thanks for reading and Robert and Sarah for replying.

  • Yes, GetGlobalSizeBySubscript returns Allocated Size only
  • Changing the third GetGlobalSizeBySubscript argument to an empty one does not make a difference in returned Size.
  • GetGlobalSize and ^%GSIZE return Used Size which is still different but not dramatically.
  • I also found an bug in my code. The lengthy InterSystems instructions to the GetGlobalSizeBySubscript code mention: ""Size - Maximum number of MB to count...Be careful to RESET this for multiple calls to the method". I'd say such a Size definition is counterintuitive but at least I got totalSize=1321.57, very close to the result from GetGlobalSize from GetGlobalSizeBySubscript(path,global,global,.Size). Final code with results is:

partialGlobalsSize(dir,global)
sub="",path="C:\Cachesys\mgr\"_dir_"\",searchGlobal="^"_global,Alloc=0,Size=0
x=##Class(%GlobalEdit).GetGlobalSize(path, global,.Alloc,.Size)
global,",",Alloc,",",Size,!  Alloc=1312,725 here, Size=725
Size=0
x=##Class(%GlobalEdit).GetGlobalSizeBySubscript(path,global,"",.Size)
global,",",Size,! 1311.9 here
totalSize=0
F  {
    /// Size - Maximum number of MB to count. If the size of the global exceeds this value,
    /// calculation stops, and an error is returned. If undefined or set to 0, then the entire range is counted.
    /// Be careful to RESET this for multiple calls to the method
    Size=0 ; Resetting!
    sub=$O(@searchGlobal@(sub)) Q:sub="" ;$D(@("^MSCG("_t_")"))
    x=##Class(%GlobalEdit).GetGlobalSizeBySubscript(path,global_"("""_sub_""")","",.Size)
    totalSize=totalSize+Size
}
global,",",totalSize,! 1321.57 here
Q