Marc Alcala · Aug 4, 2016

Global references done internally by Cache

Using the method ##class(%SYSTEM.Process).GlobalReferences() I'm able to know how many global references has been done in the process. But I'd like to know how many of those references has been done by my code and how many has been done by Cache itself.

When from a class I execute a method of another class, Cache is internally accessing globals (I suppose to get the code of the called method). I would like to not count those accesses done by Cache.


For example:

I've a method (Statistics) that counts the number of references done by another method (A). I would like to know how many of those references has been done by my class "Random" but I don't care if Cache needs to access some globals in order to be able to execute this class.


Class Stats [ Abstract ]
ClassMethod Statistics()
  Set ref = ##class(%SYSTEM.Process).GlobalReferences()
  Do ##class(Random).A()
  Write "references Increment ", (##class(%SYSTEM.Process).GlobalReferences() - ref)


Class Random [ Abstract ]
ClassMethod A()
  Set ^a = 1

Given those classes already compiled I follow the next steps:

  1. Compile Random class.
  2. Execute "Do ##class(Stats).Statistics()" -> Got "references Increment 4" -> BAD RESULT
  3. Execute again "Do ##class(Stats).Statistics()" -> Got "references Increment 1" -> GOOD RESULT

As you can see, in the second execution the reference count is what it's expected.

Any idea?


1 0 6 733
Log in or sign up to continue

I doubt that this kind of information is available.

Have you thought about wrapping global calls in a method?

ClassMethod SetVal(glvn, value)
  // track statistics, like $Username changed glvn from oldvalue to value, etc.
  set @glvn = value

I need to know also global reads, so the journal is not an option as it's not logging these reads. I'll try with PERFMON.

Thanks for your answer

If you have journaling enabled, you can parse them.

It's not an option for us.  We have lots of legacy code with different ways of modifying/reading globals:

  • Direct global references.
  • SQL (%ResultSet, %SQL.Statement, etc.).

Anyway, tanks for your answer!

Hi Marc,

you can use PERFMON [1] to collect statistics about which globals are being accessed.  This will allow you to monitor a process and then distinguish between your globals being accessed and system globals. 

That being said, I don't quite see why would would need that distinction. Where do you draw the line? When you write a sql query and it gets compiled into a routine, would you consider that being your code, or Caché's code? 

There are a couple of global accesses that will happen when you run your code, such as loading a routine (classes get compiled into routines). However, as soon as that has happened once, the routine will be in the routine buffer, so no further disc access will happen. Overall, if your application handles any amount of data that goes beyond a couple of blocks, the 'system accesses' will be negligible. 

In your example you are seeing the first time the routine is being loaded, hence the 4 references. A more realistic example would be to access 100000 random global nodes in your random class. There will still be a more accesses but 3/100000 really doesn't matter by any metric you might employ. 

I hope this addresses your concerns. 



Hi Fabian,

Thanks for your answer. The reason is just for testing, I want to ensure that some piece of code doesn't access the database. The question about the query would be yes. I will consider it as our code.

I like the idea of using PERFMON, I think that I'll be able to identify which globals I want to track.


Best regards,