B4J Question Threads for a multiPlayer-multiRoom game

LucaMs

Expert
Licensed User
Longtime User
I would like to avoid bottlenecks in a b4j server for a multiplayer game.

I have read this Erel's statement:
In most cases it is a mistake to use the Threading library

I thought of creating a thread for each game room (instance of a class clsGameRoom).
All objects and rules inherent to a room in this class.

Objects of type clsPlayer containing references to WebSocketHandler objects (these also run in their own thread).

Vaguely, something like:
upload_2015-10-2_23-48-58.png


Is the above "method" right (and necessary) or can I avoid to use the Threading library?

Am I wrong or if I use a single module to handle all game rooms (in the Main thread) I would end up in that bottleneck?


Many thanks.
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
It's the same library.

I supposed it but since the two "systems" are so different I thought I was wrong.

Thank you


[P.S. "two systems"? b4j softwares can run on Windows, Mac, Linux, b4a on Android! Uhm...
Moreover, b4j was born 3 years after b4a threading library (and I can not see an Erel's "like" for that library, which I can consider as an "approved" ;))]
 
Last edited:
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
It's just a wrapper for java.lang.Thread which is used in Android's Java code as well as Sun's Java code. That's the great thing about Google violating Sun/Oracle's patents, a lot of code is easily portable between the two systems.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Waiting for an answer, I did a "mad" attempt.

Given that every WebSocketHandler runs in its own thread, I created a WebSocketHandler class (named wshGameRoom) and a global map in the Main (mapGameRooms) containing a number of wshGameRoom instances.

I tought to avoid the use of Threading library doing so.
I do not use the websocket of those handlers, but this should not be a problem.

To test this workaround, I called a routine ("Wr") of those handlers, using CallSubDelayed:
B4X:
' wshGameRoom - WebSocket class
Public Sub Wr(Text As String)
    Log("CurrentThreadIndex: " & Main.srvr.CurrentThreadIndex & " - " & Text)
End Sub

CurrentThreadIndex results always 0 (the Main thread, I think).


[P.S. per forza: quando carico la map lo faccio dichiarando variabli locali di tipo wshGameRoom. Questa soluzione non può funzionare!
Is this not so clear? But it is more easy to me explain in italian :).
I mean: "To fill the map, I declare and instantiate some LOCAL variables of type wshGameRoom and I add them to the map, then this solution can not work!]


The (first) question is still valid, of course :)
 
Last edited:
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
The problem is that Erel had the audacity to take a few free hours :D


I suppose that a "framework" like that to which I'm thinking (which I need) published as example could be useful to many people.

But I suppose always bad: I also thought that my tools, AddLogs and lmTranslation, were useful :D (anyway, they are useful to me).
 
Last edited:
Upvote 0

Roycefer

Well-Known Member
Licensed User
Longtime User
I think you should write everything to run in the main thread. Then, when all the logic is more or less complete, you should benchmark the parts that you think will cause the performance bottlenecks. Once you've identified those parts, you can run them off the main thread using the Threading library.

I wouldn't worry too much about Erel's warning against using the Threading library. It should be ok for an Expert.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Don't use the Threading library unless you are convinced that all other solutions will be too slow. Especially not in a server solution as each connection is already handled by a different thread.

The "correct" solution depends on the specific requirements. If your app needs to interact with databases then use async queries (which are handled by a pool of threads).
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I think you should write everything to run in the main thread. Then, when all the logic is more or less complete, you should benchmark the parts that you think will cause the performance bottlenecks. Once you've identified those parts, you can run them off the main thread using the Threading library.
Thank you for your answer, @Roycefer.
I know where the bottlenecks can be (also, I have to study a method to test).
1) the game room manager; it seems to become a "server instance". I'll try to explain this better below.
2) db queries



Don't use the Threading library unless you are convinced that all other solutions will be too slow. Especially not in a server solution as each connection is already handled by a different thread.
Thank you, @Erel
Right. I will have an additional thread for each Room, which should contain 3/6 users/players, each one with its thread (websocket).
Unfortunately, I do not know in advance how many users will be. There are card games that have millions of downloads; assuming 400,000 users have your app, is it reasonable to assume that will be 1,000 users simultaneously connected? So about 1,222 threads (1,000 + (average of 3/6 players per room) * 1,000)



The "correct" solution depends on the specific requirements. If your app needs to interact with databases then use async queries (which are handled by a pool of threads).
Handle DB async queries is hard (at least for me :D). Moreover, I have to understand, since I will need a "game room manager" which should "handle" those queries and... and I have to study this solution ;):)


Unfortunately, I explain badly and you do not have time.

I thought my game server can work as the Chatroom web server example (except, unfortunately, my server will not use web pages but b4a clients only).
The Chatroom web server example has one room only; this room is handled by the ChatShared code module, which we can consider as the "game room handler" or "game engine", the fulcrum. If ChatShared was a class, I could have many ChatShared instances, then many rooms.

Am I wrong thinking so? Thinking to ChatShared (GameRoom, in my case) as the "game engine"?

How would you add other (variable number) rooms to Chatroom web server? This could/should be the solution, I think, but I don't know how, given that ChatShared is a code module. [Obviously, my problem is not change a code module to a class].

upload_2015-10-4_13-43-51.png



Thanks again for your answers.
 
Last edited:
Upvote 0

narek adonts

Well-Known Member
Licensed User
Longtime User
Maybe this solution will work.

Create a Class for each game room and run the subs of that class from the WebSocketHandlers class of that gameroom.

Ex.

Mygameroom.mysun(...)

Without callsubdelayed so it will run on the websockethandler Thread. I think it should work. You can try
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Maybe this solution will work.

Create a Class for each game room and run the subs of that class from the WebSocketHandlers class of that gameroom.

Ex.

Mygameroom.mysun(...)

Without callsubdelayed so it will run on the websockethandler Thread. I think it should work. You can try

It should work, you're right.
The only problem could be the one-way callings, from player to room and not vice-versa (still because of thread).


Thank you

I fear I can not do without calls from room to players :(
 
Last edited:
Upvote 0

narek adonts

Well-Known Member
Licensed User
Longtime User
Upvote 0
Top