ID:1907250
 
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
In optimizing a project recently, I've discovered a consistent source of problems: Proc call overhead.

atom
New()
//do something here
movable
New()
..()
//do something else here


Is five times as slow as:

atom
New()
//do something here
movable
New()
//do something here
//do something else here


The supercall look-up should exist at all. In my opinion, the compiler should use ..() as a compilation cue, find the compiled bytecode offset of the supercall proc, set the return position to the next token, jump to that code offset, and any returns will set the current ret value and jump back to the return offset.

What it looks like is currently going on, is the super proc is being looked up every time it's called.

DM's compiler should just be using jumpcodes to navigate functions. This should not have the kind of overhead we're seeing.
I'm not sure if you're fully aware of how the BYOND VM works. There is a dedicated "supercall with the same arguments as this function" operation. To my knowledge the parent proc is two pointers away.

The overhead you're seeing is likely good 'ol function invocation overhead (in the form of having to allocate space for arguments, locals and other shenanigans).
Probably part of the overhead is copying args. I'm not certain what happens if you alter an arg before a supercall.

I suspect this is a nightmare to handle at the compiler level, but I'm not sure. Looking up the type chain (or at the current type for other procs) isn't something I'm sure I can do at compile-time.
I'm not sure if you're fully aware of how the BYOND VM works.

I'm definitely not. I've got a working knowledge of what's going on behind the scenes based on assumptions. Usually they are pretty close to right, but I've always admitted that you are the expert in the VM area, Tobba.

You still have to admit, thought, that a 5-fold performance gain simply by not invoking a function implies that some work needs to be done to improve this.
In response to Ter13
Ter13 wrote:
I'm not sure if you're fully aware of how the BYOND VM works.

I'm definitely not. I've got a working knowledge of what's going on behind the scenes based on assumptions. Usually they are pretty close to right, but I've always admitted that you are the expert in the VM area, Tobba.

Of course what you're describing is what would ideally happen, but I think the best you could currently do is compile in the proc ID of the superproc, and I'm not sure if that would help much (AFAIK the ID of the superproc is stored with each proc definition of the DMB).

I'm not 100% on the last part though, if that's not the case it should change. The compiler is already clever enough to remove the by-name proc lookup on normal calls if it knows exactly what proc you're referring to.
The opcode number is 0x2C if Lummox wants to check it out.
I'm not certain what happens if you alter an arg before a supercall.

The arg you modified is maintained.

Actually, you can pass around the args list as an argument to another function and modifications of that args list will actually modify that function's args list.

proc/testargs(a1,a2,a3)
modargs(args)
world.log << a2
proc/modargs(list/l)
l[2] = "this works"


As you can see, the output is "this works". My EventLib actually depends on this behavior. The args list of the event trigger is passed to the bound events as an argument so that any bound events can modify the outcome of their intended proc by changing the arguments and returning void.

proc/testproc(a1,a2,a3)
modargs(arglist(args))
world.log << a2
proc/modargs()
args[2] = "this works"


^The above doesn't work though, because it duplicates the args list rather than passes it.
That's absolutely horrifying.
In response to Tobba
Tobba wrote:
That's absolutely horrifying.

I think it's a quite useful quirk.
args is a reference type...

In V8, modifying or passing the arguments special var causes most optimizations to bail out... its kind of a special case by necessity.