if there will be an error this won't change the namespace back even with the "new $namespace" command

It would be still "%SYS" inside the `catch` block, so it's unsafe to call any code in its context. Even if you write something like this:

 ...
 try {
   new $namespace
   set $namespace="%SYS"
   ...
 } catch ex {   // process the error
   set sc=ex.AsStatus()
   do ..logErr(sc) // do some debug logging
 }
 return sc

and the ..logErr() call will be successful (generated .int code was not split into parts), the global where the log goes should be the same for all namespaces (e.g. mapped via %ALL pseudo-namespace). There are so many complications that it seems better to avoid any error processing inside the `catch` block above returning the error code. BTW, it sounds reasonable in any case, not only in this one associated with %SYS.

It would change. I mean that try/catch is still needed to handle exceptions that can occur during namespace change or after the change, working in "%SYS" (mostly security violation errors). Otherwise the method can produce unsolicited exceptions.

The key feature here is `new $namespace` command rather than the method of its changing, while `set $namespace="%SYS"` seems to be the preferred one as it is well documented and good looking.

I'd still use try / catch outside namespace changing as there can be security errors on attempt to do it. I mean something like this:

classmethod DoSomethingInSYS() as %Status
{
 set sc=$$$OK
 try { 
   new $namespace
   set $namespace="%SYS" 
   // do something, e.g. config change
 } catch ex {
   // process the error
   set sc=ex.AsStatus()
 }
 return sc 
}

Jack, your results are easy to explain.  When you use $list*, you must perform conversion to string which adds extra cost.

When you check some conditions inside the loop, you add some cost as well, how much - it depends on checkup method.

So, the best results should be achieved with Robert's and Alex's approaches. I'd prefer the Robert's one as it doesn't force special processing of the first element.

Agree with you: to guess that the "kosher" way to get a current directory is to call 

set currentDir = ##class(%Library.File).NormalizeDirectory("")

one should not be a priest; being a modest monk should be quite enough.

Thanks for the good advices, guys.
Robert, you should be aware that $zu(12) (a.k.a. $$$FileMgrDir) is usually not the same as $zu(12,""): 

QMS>w $zu(12)
f:\intersystems\cuni\mgr\
QMS>w $zu(12,"")
d:\bases\qms\

My writing was just a result of quick prototyping using the terminal. Just for curiosity, I dived into %occFile.inc and there was no macro to get the current directory. It is possible through class method call (##class(%Library.File).NormalizeDirectory("")), while all this stuff looks like a great overkill for such a small sample.

 set status=statement.%Execute($zu(12,""),,GlobalName,,,FastFlag)

runs fast enough with FastFlag=1.

GSIZE is way faster than the analogous ObjectScript functionality

%GSIZE is written in ObjectScript. What "analogous ObjectScript functionality" do you mean?

As you probably know, there are two explorers in VS Code: client-side (<Ctrl-Shift-E>) and server-side ("ObjectScript", which comes with InterSystems extensions). If you don't see your routine in the first one, you just need to export it using the second one.

Thank you, John,

it sounds promising, while I've found only a facility of adding web links here. My case is a "plain" COS command line to execute. In the meanwhile, it seems that I've found a solution; if anybody is interested, I'll write a couple of words about it earlier.