Question Norman W. Freeman · Aug 14, 2024

Iterating ^$GLOBAL is very slow

I use the following code to loop trough all globals : 

set name=""for
{
   set name=$order(^$GLOBAL(name))
   quit:name=""
   write name,!
}

However this is really slow : about 1second per node. 

I ran debugger, and it seems most of the time is spend in "%SYS.GD Visible" function. There is a comment that says : 
"Sees if globals in dataset are visible to our namespace"
This function loop on a global named ^mtemp which contains lot of records (10K or more).
I have cleared global, hoping it has been filled by another process but it's not (it seems to be filled by %SYS.GD)

Why is it so slow, Is there a way to make this faster ?

Product version: IRIS 2021.2
$ZV: IRIS for Windows (x86-64) 2021.1 (Build 215U) Wed Jun 9 2021 09:39:22 EDT

Comments

Alexander Koblov · Aug 15, 2024

^$GLOBAL likely does not cache the list of the globals in the current namespace

So each time you do $Order(^$GLOBAL(name)) it gets the list and looks which global is next after the one in the name. That's fine because globals might appear and disappear between the calls.

If you'd like to loop through the globals -- use merge, and then loop through the temp variable a

merge a = ^$GLOBAL("")

Note, that your loop is much faster if you run it in the database, not namespace, as here ther are no possible mappings to account for

USER>s z1=$zh,n="" f  { s n = $O(^$Global(n))  q:n="" } w $zh-z1
3.302887
USER>zn "^^..\user"

...iris\mgr\user\>s z1=$zh,n="" f  { s n = $O(^$Global(n))  q:n="" } w $zh-z1
.098734
0
Norman W. Freeman  Aug 17, 2024 to Alexander Koblov

Thanks for your reply. I didn't know you could run code in database. My guess is that in this context you can only access database globals, not the routines/classes, am I right ?

0
Alexander Koblov  Aug 19, 2024 to Norman W. Freeman

Depends on which globals are in the database. If you have separate code / data databases for the namespace, then yes -- you'll see only data or only code related globals

0
David.Satorres6134  Aug 19, 2024 to Alexander Koblov

Hi Alexander,

before running the second command, and in order to get the right numbers, shouldn't you clear the buffers so system takes it again from the disk?

ClearBuffers^|"%SYS"|GLOBUFF()
0
Alexander Koblov  Aug 20, 2024 to David.Satorres6134

Hi David

Not really! I want to prove that ^$Global is faster from the database directly, so I would benefit from the buffers ;-)

Seriously though -- yes, good point. Even on the second and consequent runs ^$Global from the namespace is noticeably slower, so it uses the same buffers as the ^$Global from the database directly

0