Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
The "Any" and "Any+UP" macros are great tools for flexible input systems. It would be nice to also have new tools for precise input systems.

This could be a change to the current Any macros or a new type of macro entirely. In the command, instead of [[*]] being replaced with the button name in string form, it would be nice to receive the button's raw integer ID instead (the hex value passed in from the OS).

An example of where this would be useful is a game where it is preferable to process input multiple times per tick, like a fighting game. Currently a way we can do this is by setting up the Any macros to call a client verb that has set instant = 1. The verb's argument is the button pressed in string form.

The problem here is that in cases like this we need to process that input as fast as possible so the player doesn't think input feels laggy or unresponsive. Processing strings is expensive in comparison to integers and when we're talking about processing strings multiple times per tick that cost really starts to matter.
Processing strings is expensive in comparison to integers and when we're talking about processing strings multiple times per tick that cost really starts to matter.

Assuming this was true the difference would boil down to ones of nanoseconds, and you have until the next tick (upwords of 10 million nanoseconds away at 100 world.fps) anyways before the client will even be sent the response.

Unfortunately it's not true though, in byond comparing strings are equivalent to comparing numbers because byond references strings as a numeric index internally, meaning that byond doesn't have to go through and check each character individually, the primary thing that would slow down string matching.

MSO is right; the difference in performance is basically non-existent at the server end. The only thing you'd see is the string tree maybe expanding to fit in strings it hadn't already seen. Otherwise there'd be no difference.

Keeping a list of currently-pressed keys is actually far easier with strings, because you can use an associative list instead of a fixed size.
In response to MrStonedOne
In the system I'm prototyping world.fps is irrelevant to resolving input. What I'm trying to do is entity interpolation. It's more of an experiment than anything because I haven't done anything like this in byond before and it may not even be possible with how client and world work behind the scenes but I'm giving it a shot.

The idea is that input is handled completely by the client. When an input comes in, it's stored in a buffer. That buffer is processed every client tick, which is currently defined to be twice as fast as a world tick. Later on, assuming everything works out, I'd like to let the client run multiple times faster than a world tick if the client's performance allows.

At the beginning of the client tick, client/Move() is called and it handles the response to input within the buffer. The game is simulated by the client more-or-less entirely in the time-frame between world ticks.

Once the world tick comes around, it just takes a look at what the client did and makes sure everything that was done was legal based on what other clients did. If everything was legal, which it should be 99% of the time, nothing changes. If not, the server is authoritative so it steps in and makes the changes necessary for the client's actions to be considered legal.

The difference doesn't boil down to ones of nanoseconds. If the value passed to us is the hex value straight from the OS we're ignoring all the overhead behind strings in byond. Comparing strings may be equivalent to comparing numbers but initializing a string is certainly not equivalent. We're talking library calls followed by whatever overhead goes with setting up that internal numeric indexing and anything else.

On top of time performance, strings are most certainly memory hogs in comparison to integers and when 100+ players are thrown in, each with their own input buffer, that's a lot of extra memory being eaten up.
In response to Lummox JR
I talked about why the difference between performance shouldn't be non-existent in my reply to MSO.

If I don't care about what time a key was pressed, if I had just the hex value from the OS, keeping track of what keys are pressed just becomes an integer variable like so:
keys_pressed |= key for a key press
keys_pressed &= ~key for a key released

That's the idea at least, we'd hit byond's 16-bit limit due to number of keys but that can be gotten around by breaking up the keys_pressed value into a few values.

If I do care about what time a key was pressed (and I do), I can throw them into a circular buffer where I don't have to deal with the time complexity of an associative list lookup.
In BYOND bitwise operators are painfully slow anyway, probably due to all numbers being stored as floats
In response to Bmc777
But wait, client/Move() still only happens on the server. The only commands happening on the client are the client-side verbs such as .winset (more listed in the Skin Reference), which either never end up communicating with the server at all, or sends a verb call to the server (e.g. .north). No DM code is ever executed on the client.

There's already a client.fps var that increases the framerate of animations (including animate() and gliding between positions in tile/pixel movement), but it won't increase responsiveness since commands are still just queued up and executed at the world tick rate.
You couldn't use bitflags for keyboard stuff--not universally--because the size of that hex number would be in the neighborhood of 300 bits or more. Having a list with a bunch of 16- or 24-bit bitflag values wouldn't be any better. The math involved in the soft-code implementation would completely wreck any advantage you could imagine there being over an associative list. Frankly a fixed-size numeric list would perform much better than bitflags, as you could do O(1) lookups without extra math.

But associative list lookups are very fast, especially when said list is small. Even if you never delete items from the list (IMO it's a little easier not to), it wouldn't ever grow past a point where the lookups would take very long. This is absolutely the fastest solution.
In response to Lummox JR
From a pure speed perspective you're of course 100% right and I agree with everything you said. The problem is we're still eating up a comparative ton of memory with an associative list of keys for every client connected.

Even worse, we're eating up a ton of precious cache memory with all those associative lists since, even on average, they're being referenced multiple times a tick.
An associative list takes up a small amount of space for the list struct, a contiguous amount of memory for the values in the list, and also a tree item structure for each key/value pair. For an associative list of key presses, all of this adds up to mere peanuts: far less than 1K per client in typical usage, though you could probably pass that if you pressed and released a whole lot of keys over the course of the client's run and didn't remove them from the list (as there's really no need to). A full numeric list for keys would take up over 2K.

I'm also not sure what you mean about cache memory, unless you're referring to the CPU cache, but BYOND being an interpreted language means there's no way to predict how any given piece of code affects that. If you mean the BYOND cache, as in the .rsc file, associative lists have no relationship to that at all since it only applies to files.

Trust me, you have nothing to worry about here in terms of performance, memory or CPU.
In response to Lummox JR
A lot of interpreted languages have a caching system under the hood, I just assumed byond has that too but I guess only for files like you said. Not being able to / not having to worry about keeping cache in order, combined with byond bitwise operators apparently not offering any performance benefits, (didn't know that before I made this post) basically blows all my concerns here out of the water so I guess that's that.

Thanks for your responses, definitely helped clear some stuff up for me and is appreciated.
Yeah, basically the code would have to operate at an extremely low level to see performance benefits vs. a simple associative list.

Internally, Dream Seeker does have a list in numeric order. However those codes are undocumented and therefore subject to change (at least anything beyond 256).

Login to reply.