8000 Event channels/rooms · Issue #388 · feathersjs/feathers · GitHub
[go: up one dir, main page]

Skip to content

Event channels/rooms #388

@ramsestom

Description

@ramsestom

In many cases, service events need to be filtered to restrict their emission to a limited set of clients (1 to 1 or 1 to few users messages in a chat app for example). Filters allow to do this but at the cost of iterating through all connections, for each event... This can cause unnecessary server load when the number of events and/or connected clients is important.
One nice feature that could be considered to improve this would be to add some possibility to provide a list of connections to be considered by the dispatcher along with the service event. That way, the foreach loop (io.sockets.clients().forEach(function(socket) {...} ) could be performed only on this restricted list of connections (and on all connections by default, like already the case). Alternatively we could also pass a list of user _ids and keep a mapping of _id to connection automatically somewhere in feathers.
With this improvement, it would be possible, for example, to maintain a list of user._id <-> connection (if not handled by feathers) and to simply call the dispatcher to emit an event (like a 1 to 1 message) on a specific connection (retrieved directly from the user._id -> connection hash table, which is much quicker than having to iterate through all connections (with filters) to find the targeted one)

To give you an idea, I made a really simple benchmark to test the difference between making each time a really simple test (like connection.user._id === message.to_user_id) compared to looking for a given entry into a connection hash table :

Here are the results:

with 10k connections:
foreach method: 3.608ms
hash method: 0.073ms

with 100k connections:
foreach method: 27.761ms
hash method: 0.126ms

with 1M connections:
foreach method: 284.016ms
hash method: 0.288ms

So,, until 10k connections, the difference is still "reasonable". But passed this, the difference start to be significant (pretty much 1/3 second just to loop through connections in the dispatcher, for a single event, when 1M users. Meaning you wouldn't be able to treat more than 3 events/s (at best case) when 1M concurrent users whereas you could treat 1000x more if you knew the connection where to dispatch a priori).
And you have to keep in mind that number of events per second generally grows with number of users...
So the foreach loop in the dispatcher can became a real bottleneck if you want to use feathers for big apps... (If you have 1M concurent users, you wouldn't be able to treat more than 3 event/second on each node because of this)

Here is the code used for my really simple benchmark:

var nbconnections = 1000000;

var array = new Array(nbconnections);
console.time("foreach method");
array.forEach(function(socket) {
    if (socket === 0){

    }
});
console.timeEnd("foreach method");


var hash = {};
for (i = 0; i < nbconnections; i++) {
    hash[i+'']=i;
}
console.time("hash method");
var conn = hash['1000'];
console.timeEnd("hash method");

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0