So testing shows the old way was better in this case.

Failure
iris session ${INST} -U %sys << EOF

w "stopping the mirror 1 is sucess: " zw ##class(SYS.Mirror).StopMirror("MIRROR")

h

EOF

%SYS>

%SYS>
stopping the mirror 1 is sucess: "0 "_$lb($lb(2050,,,,,,,,,$lb(,"%SYS",$lb("e^Shutdown+7^MIRRORMGR^2","e^zStopMirror+4^SYS.Mirror.1^1","e^^^0"))))/* ERROR #2050: Mirror configuration not loaded */

%SYS>
Sucess
$ iris session ${INST} -U %sys << EOF
>
> zw ##class(SYS.Mirror).StopMirror("MIRROR")                                  <
> h
> EOF


%SYS>

%SYS>
stopping the mirror 1 is sucess: 1

%SYS>

Same either way :(
iris session ${INST} -U %sys '##class(SYS.Mirror).StopMirror("MIRROR")' ;echo $?
0

An easy way is setup Operating System–Based Authentication
in %sys
^SECURITY
12) System parameter setup
2) Edit authentication options
Allow O/S authentication? Yes   

This allows scripts like this

iris session ${INST} -U %sys << EOF

w "stopping the mirror 1 is sucess: " zw ##class(SYS.Mirror).StopMirror("MIRROR") h
EOF
Once an IRIS LDAP account exists it does not appear to be different local account.

You can do this too:
iris session [instance] -U [namespace] tag^routine

The only way to get an estimate I can think of is running the compact against a SAN snapshot on similar hardware.
The free blocks could be anywhere in the file and that plays a big role.

Here are some numbers:
Current Size: 2332950 MB
Freespace at end of file: 300 MB
Total freespace: 8957 MB
Blocks Scanned: 10850564
It took 1 hour 44 minutes

The truncation was almost instant.

First my experience is on IRIS.DATs that were 2Tb is size and experience will vary widely since where the free space is is what matters.

There are two different compacts:
Compact globals in a database
Compact free space in a database

If all you want to do is compact free space things are easier.
Do it in small steps with ^DATABASE

Current Size: 2307950 MB
Total freespace: 8564 MB
Freespace at end of file: 18 MB

Target freespace at end of file, in MB (18-8564):200

One great feature is you can cancel if you need to.
Press 'Q' to return, 'P' to pause, 'C' to cancel:

Truncation can be done in the same way in steps.

If you have one I suggest that you do this on your DR instance, move to DR and then do it on what was production.

If you are using 8k blocks for IRIS you should start thinking about the 32Tb limit for 8k databases.

You need to run an integrity check after you are done.

If you wanted to run compact globals that is much more complex.

If the underlying storage does deduplication you should make sure you have extra space at that layer.

I ran your code against a production snapshot and got:
elapsed: 7365.54051
w count
57434071

and

elapsed: 10925.91166
w count
43841315

As you pointed this is a problem in approach.

This is on enterprise hardware so that is not the issue.

I did change your code to use a second subscript ^XXX("YYY",sub)

as an example of a better approach
w $Order(^XXX("YYY",""),-1)
57435810

There are several major steps:
Mount the LUN or LUNs as a filesystem
Have the required namespace
Mount the CACHE.DAT in Cache. Look at ^DATABASE
Have the required global mappings.


My suggestion is to install another instance of Cache on the server.
That way you might be able to update the cache.cpf using the one from the old server as a template.

This is a pretty complex task.