Multithreading with Web Workers

Discussion in 'Javascript/Plugin Support' started by Fhntop, Jan 2, 2018.

  1. Fhntop

    Fhntop Villager Member

    Messages:
    28
    Likes Received:
    22
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    Hi,
    I've been doing some research on web workers and I wanted to ask if anyone has been using them in MV. Any other experiences outside of MV you wish to share are also welcome :D

    I'm having some performance issues and I believe the main problem comes from the physics engine, Oimo.js, running at (supposedly) 60fps. I'm thinking if splitting it from the main thread would be a good idea, although a bit tedious...
     
    #1
  2. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Actually, a lot of cpu power is wasted on update cycles. So I'd rather create custom classes without unnecessary update cycles and put loading on a second thread to separate game logic and resource handling.
    Btw. I had no idea that MV uses Oimo engine :D
     
    #2
  3. Fhntop

    Fhntop Villager Member

    Messages:
    28
    Likes Received:
    22
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    Oh, sorry, I should've been more specific haha
    MV has a pretty simple collision system, while Oimo is a 3D physics engine so it's more cpu-intensive xD

    What do you mean with unnecessary update cycles? I thought the Sprites and Characters always had things to do during their updates.
     
    #3
  4. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Characters... Some need it, some don't.
    Sprites don't need it. For example TilingSprites don't have an update function. But normal sprites do. But why? Texture update is made through objects, not through sprites.
    But yeah, if you're using Oimo, I guess I cannot help you. My computer runs that demo on 15 fps... :D
    But thank you for the idea of using web workers, I had no idea they existed :D
     
    #4
    Fhntop likes this.
  5. Fhntop

    Fhntop Villager Member

    Messages:
    28
    Likes Received:
    22
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    I saw that the Sprites have a reference to their Character but not the other way around.
    I'm not familiar with TilingSprites but I thought Sprites update their position and alert the character when the current animation is over, among other things, so I don't really see how to avoid updating them...

    You're welcome! I thank you for your idea of loading things on a different thread, that seems like a nice way of avoiding some texture loading lagging issues :D
     
    #5
    Poryg likes this.
  6. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Welcome! This is actually the reason why I recently began studying Java to be honest :D I found a program that is able to build a standalone exe launchable without Java VM for free, so I thought that it could be interesting to convert the final game to Java, compile it and then make an executable from that. Java is a multithreaded language and since JDK7+ supports ECMAScript 5 and JDK9 has some support for ECMAScript 6 (although it still hasn't come to terms with JS's var, let and const), it might work just fine :) But that is off topic.
    Well, I guess I should take a look at the code again :D Haven't seen it for a while, so I guess I made a mistake there.
     
    #6
  7. peq42_

    peq42_ Yeet Veteran

    Messages:
    465
    Likes Received:
    274
    Location:
    Brazil
    First Language:
    Portuguese(BR)
    Primarily Uses:
    RMMV
    Hey one of you guys know a way to improve multhread in MV games?

    A plugin/tutorial that could do this would be really welcome by everyone, i think.
     
    #7
  8. Fhntop

    Fhntop Villager Member

    Messages:
    28
    Likes Received:
    22
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    Sounds great! I've used Java years ago so I don't know the current state of it but I enjoyed it as one of my first languages. Nowadays I prefer Python xD

    Multithreading is a kinda complex topic (something can work and then go wrong in a different run and it may take a long time to figure out what the issue is). I don't see much use of it in vanilla MV, except maybe for what @Poryg said, loading and manipulating resources before they're used. If you wanna take a look, search for "javascript Web Workers" on google. I understand they share data using messages but I haven't used them yet.
     
    Last edited: Jan 2, 2018
    #8
  9. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    @elpeleq42 There is nothing like improve multithreading in MV. Javascript is a single threaded language. Of course there are cetrain ways to create multithreading - web workers, browsers have their own method of doing it too, but... Just like RGSS3 doesn't support 3D, so it's only possible to create fake 3D (Mode 7), I don't see a reason why it would be possible to create true multithreading when JS is single threaded.

    I think the only way to have real multithreading would be to either make a multithreaded javascript or to convert the game to some multithreaded language (like Java or C#). This means some really difficult things though, because Java cannot deal with JS primitives and C# doesn't have the best support for javascript, because you essentially need to create your own interpreter. So it might be better to rewrite all scripts so that they are in that language's format, for which C# would be a better choice than Java, because C# is difficult to reverse engineer. But then again, this could lead to a total transformation of the game's engine, because if you intend to convert the game to C#, you're not limited to PIXI in terms of graphics rendering.

    Improving multithreading in MV by default is also difficult due to the fact that MV is only optimized for single core use, so it won't use more than 1 core (in some cases 2 cores actually, because cpu are also a bit more advanced nowadays in terms of handling tasks). Still it means the power you can use is very limited.
     
    #9
  10. peq42_

    peq42_ Yeet Veteran

    Messages:
    465
    Likes Received:
    274
    Location:
    Brazil
    First Language:
    Portuguese(BR)
    Primarily Uses:
    RMMV
    That idea of webworkers(if possible to add to MV) would be really great!
    I mean, it's basically the same thing as multithread, isn't it? Running things in the background, using other CPU threads/cores, so you don't overload the main thread causing problems for the aplication.
    This could solve the problem of "Lag" when executing many parallel events(in a single thread thing, they will lag a lot. But if executed in the background, things get a lot better for the main part of the game). Also, loading could be improved with this(dividing some of the load. One part the main core loads, the other is loaded in the background by web workers. Once the first part loads you create a "check" to see if the second part was loaded, and when it be, you go to the next map).Plugins too could benefit from webworkers in many ways.

    That idea @OP had was really great... I wish i knew javascript enough to implement those things(mainly, how to make MV use more than 1 thread)

    EDIT: Hey what if we change the way that "index.html" calls some of the main javascripts? Like this: https://www.w3schools.com/html/html5_webworkers.asp
    If we start calling some of the core javascripts(like RPG_Objects, RPG_Scenes,etc) in a "web worker way", could it improve performance?Creating 1 webworker for each(1 for plugins, 1 for RPG_objects, one for RPG_Scenes,etc).
     
    Last edited: Jan 2, 2018
    #10
  11. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Maybe it would be better to talk to @Joy Diamond about that.
    EDIT: No, creating a web worker for each script is useless. Web workers don't have access to DOM and global variables, which means even $gameVariables and stuff. Their use is very limited.
     
    Last edited: Jan 3, 2018
    #11
  12. Fhntop

    Fhntop Villager Member

    Messages:
    28
    Likes Received:
    22
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    I don't think it would work with parallel processes. As far as I've seen, workers run isolated from each other and the core thread. They comunicate via messages, copying the data. If you had a parallel process on a worker, you'd need to have access to every single thing it uses ($gamePlayer, $gameMap, etc) and it'd need to either be copied to it (too much overhead) or send a message to the core thread asking for the specific data it requires, or ask it to make any changes to the real object (which I think basically makes the worker useless).

    If this kind of multithreading is useful for a plugin, I think the best option would be for the creator to implement it as they see best. In my case it seems it could work since the physics can do all the heavy calculations on their own thread and then send an update to the core thread with the pair <entity_id, {position: X, speed: Y, ...}>. I still haven't got to test it, but going from no-physics ~120 fps to physics ~60 fps on the same thread I believe it would have some performance gains.

    In Java or C you can share pointers (or references) which avoid cloning the data for multithreading and as such it's much more useful. It also makes it more easy to for something to go wrong...
     
    #12
    Poryg likes this.
  13. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Sadly you're right. Workers don't have access to global variables and to DOM elements, meaning they can handle neither game logic nor graphics. However, they have access to functions, so maybe it could be done so that global variables are used as a parameter of a function that transforms it to local variables, calls a function and passes it to the second thread. This way it could be used for calculations. And since MV engine is already built on a functional programming, it wouldn't even look that ugly. But yeah, I'd still primarily use it for loading.
     
    #13
  14. peq42_

    peq42_ Yeet Veteran

    Messages:
    465
    Likes Received:
    274
    Location:
    Brazil
    First Language:
    Portuguese(BR)
    Primarily Uses:
    RMMV
    But do they have acess to .json files?
    If yes, information from global variables/Dom elements could me saved in a "global config" json file and then read by the workers, couldn't they?
     
    #14
  15. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Yup, they have access to json files. Json files are also, from what I found, the only method multiple workers can communicate together.
     
    #15
  16. peq42_

    peq42_ Yeet Veteran

    Messages:
    465
    Likes Received:
    274
    Location:
    Brazil
    First Language:
    Portuguese(BR)
    Primarily Uses:
    RMMV
    Well if there be a way to automatically store(using a plugin or something) all global variables and what ever more web workers cannot read directly in a json file(to not create problems with that, maybe everything should write AND read those informations from a json, not within plugins and .js files), then all that i/OP said may work fine, right?

    Edit: Wow... using workers can improve A LOT the performance
    Look at this:
    http://pmav.eu/stuff/javascript-webworkers/
    in the benchmark part, when it ran using 1 worker, it took 10k ms. With 2 it was 5k. With 4 it goes to 2.7k , up to 2k using 16 workers. That's 5x faster than using one(wich probably is even more, comparing to using noone, because while basic javascript is singlethread, web workers are, each one, multithreaded)
     
    Last edited: Jan 3, 2018
    #16
  17. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    There is an option to store everything in a json file. There is just one major issue. Frame drops. As you may know, saving a file in mv causes freezes of sometimes even multiple seconds. Imagine what would it turn the game into if you made files every few seconds or even everytime a switch or variable turns on or off. Insane.
     
    #17
  18. Fhntop

    Fhntop Villager Member

    Messages:
    28
    Likes Received:
    22
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    I think that still requires copying the data. To move something from a thread to the other, it needs to be duplicated. Unless you use a shared memory buffer, but I think that's a relatively new thing in js. I don't think you can copy functions with their context. As for functions, you could pass a string and then create the function on the other thread, but without the context of the 1st thread (unless you copy it, but then you lose the original references, and any changes need to be sent back).


    I think this is possible. Writing to disk is however a worse performance bottleneck than using things on memory. Even if you don't save to disk and pass it as a message to another thread, you have to detect every change made on a shared object and replicate it on every copy. I'm afraid doing it the right way would require huge changes on MV's base code, and I'm not sure it's worth the improvement.

    This is because that problem is parallelizable. Not everything can be improved using multithreading. For instance, I can't really think of a way of improving the performance of a inherently sequential problem with it. I'm sorry I can't give you a more specific example but I'm sure you can find one with google :D
     
    #18
  19. Poryg

    Poryg Dark Lord of the Castle of Javascreeps Veteran

    Messages:
    3,996
    Likes Received:
    10,114
    Location:
    Czech Republic
    First Language:
    Czech
    Primarily Uses:
    RMMV
    Since these benchmarks are ran on a basic calculation, these results can't be taken for granted. For example you can't use multiple workers to load a file, because in order for the filesize to be determined, it needs to be loaded first. So this can be done with only one worker. But the fact that you can offload the main thread definitely is a performance boost.
     
    #19
  20. BigEd781

    BigEd781 undefined method 'stupid_title' found for nil:NilC Veteran

    Messages:
    940
    Likes Received:
    303
    Location:
    Austin, TX
    First Language:
    Dothraki
    Primarily Uses:
    N/A
    Just to be clear here; web workers are _not_ a feature of JS, they are a feature of the browser.
     
    #20

Share This Page