Cazka / diepAPI

An API for https://diep.io
MIT License
15 stars 8 forks source link

Faster EventEmitter #63

Open supahero1 opened 1 year ago

supahero1 commented 1 year ago

So needless to say, EventTarget is pretty damn slow. I wrote an identical interface to yours in event_emitter.ts:

export class ObjectEventEmitter {
    #events: Object<string, EventCallback[]> = {};
    /**
     *
     * @param {string} eventName The name of the event
     * @param  {...any} args The arguments that will be passed to the listener
     */
    protected emit(eventName: string, ...args: EventCallback[]): void {
        const listeners = this.#events[eventName];
        if(listeners === undefined) return;
        for(const callback in listeners) {
            callback(...args);
        }
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    #set(eventName: string, listener: EventCallback): void {
        const listeners = this.#events[eventName];
        if(listeners === undefined) {
            this.#events[eventName] = [listener];
        } else {
            listeners.push(listener);
        }
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    on(eventName: string, listener: EventCallback): void {
        this.#set(eventName, listener);
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    once(eventName: string, listener: EventCallback): void {
        this.#set(eventName, function() {
            listener();
            this.off(eventName, listener);
        }.bind(this));
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    off(eventName: string, listener: EventCallback): void {
        const listeners = this.#events[eventName];
        if(listeners == undefined) return;
        const length = listeners.length;
        for(let i = 0; i < length; ++i) {
            if(listeners[i] === listener) {
                listeners.splice(i, 1);
                return;
            }
        }
    }
}

Except line 2 doesn't work lol, and I don't know how to fix that.

Here are some benchs:

image image

For the second bench with offing listeners, I also shuffled the initial array of functions that were added to the emitter classes, so deleting wouldn't be just straightforward popping the head of the array everytime.

I also compared Map() with a simple object, object being faster by about 27%.

Let me know of any issues with this.

Cazka commented 1 year ago

thanks for the contribution. I will consider using this.