- Joined
- Jun 25, 2021
- Messages
- 862
- Reaction score
- 1,066
- First Language
- English
- Primarily Uses
- RMMZ
TLDR: Obfuscated plugins can harm your game's performance.
So this community has already seen a lot of debate about code obfuscation, to the point where the topic has seemingly already been beaten to death. But for some reason, I've never actually seen anybody bring up the biggest concern that I've always had about obfuscating plugins: the performance impact.
There are different ways that one can obfuscate code. More minor forms of obfuscation tend to have little to no negative performance impact. But there are also some more aggressive means of obfuscation, that can easily cut the performance of your code in half (or worse). If you're writing a website, or a simple web application, or something else that's not really performance critical, then there's probably not any issue with using the latter type of obfuscation. But if you're writing code for a game engine... it's generally considered to be very ill-advised to intentionally reduce the performance of your code to such a high degree.
Unfortunately, the obfuscation method that I have seen being used by some very ubiquitous plugin developers is actually that latter (aggressive) form of obfuscation. You might be thinking: "Who cares? There's no way it makes *that* big of a difference." Well here, let me show you a quick example of how much of a difference it can actually make:
To summarize what you saw in that video, I used VisuStella Weather Effects to run a stupid amount of weather effects at the same time. Then, without changing anything else, I swapped the plugin out for a de-obfuscated version and ran the exact same weather effects. With the obfuscated version, I was averaging around 27-ish FPS. With the de-obfuscated version, I was getting a solid 60 FPS (and it possibly could have gone even higher, but it was capped due to VSync). That means that I more than doubled my FPS simply by de-obfuscating that one plugin. Another way to say it is that the obfuscation of that plugin was literally cutting my FPS in half (or worse).
Now you might be thinking: "Who cares? It's probably just an issue that's specific to Weather Effects, and I don't use that plugin anyway." Unfortunately, that's not the case. For those who don't know how plugins work in RPG Maker, I'll kinda summarize it. A plugin works by overwriting parts of the original engine. So when you install a plugin, you're overwriting chunks of your engine with that new code. So when you install a bunch of plugins with code that is sub-optimal, then you're essentially scattering doodoo all over your game engine. And unfortunately, with the method that VisuStella chose to obfuscate their plugins, it's pretty much impossible for their code to *not* be sub-optimal. I'll go ahead and explain some more tests that I have conducted, in case you want more examples, but I'll put it in a spoiler tag so that you can easily skip it if you don't.
Hopefully by this point, you understand that the code obfuscation really is coming with a non-negligible performance cost. But you might be wondering why. What could it possibly be doing that is causing it to hurt performance to such an extent? Well, I'll try to explain it, but I also need to try to keep it vague, because I don't want to accidentally spur a discussion about how to actually de-obfuscate the code:
So does this mean that you should never use obfuscated plugins in your game?
I wouldn't go *that* far. Personally, I do use some VisuStella plugins. It is worth noting that most of my tests were being conducted under unrealistically extreme situations, so it doesn't necessarily mean that using an obfuscated plugin is absolutely going to ruin your game. You're probably never going to need to have more than 180 parallel events spamming random spell animations all over your map at any given time.
But on the other hand, it is important to note that I was only using one plugin for the tests, and I didn't have anything else going on (other than the test) at that time. In an actual game, you're going to have multiple plugins doing multiple things at any given time, and you might have all kinds of other stuff going on in your map at that time as well, so it's certainly feasible that those things could add up to create some performance issues, and heavy usage of obfuscated plugins will certainly increase the chances of that happening. Each time you add an obfuscated plugin to your game, you're overwriting more sections of your game's engine with poor-performing code.
So at the very least, I think it's important to be cognizant of the fact that there is a performance cost for adding an obfuscated plugin to your game, and to just make sure that your game can afford that performance cost, and that the functionality that the plugin provides is worth that cost. When considering using an obfuscated plugin, maybe at least make sure that you actually need/want most of the functionality that it provides. For example, if you *just* want to add self variables to your game, then maybe think twice before grabbing a plugin that does that plus 99 other things that you *aren't* looking for. In that case, it might be in your benefit to at least check for an alternative plugin.
And if you happen to be a plugin creator, I'm not trying to tell you not to obfuscate your code. That's your right, and it's not really my place to say anything about it. But I do still feel that it's important for you to be fully aware that in doing so, you *are* pushing a cost onto your customers, and onto the customers of your customers. So I would at least implore you to ask yourself if what you're gaining from obfuscating your plugins is actually worth the price that your customers/users will have to pay for it.
Well, I've kinda fizzled out and don't want to type any more at this point, so I guess I'll end things here. I do feel that I should add a disclaimer and mention that in making this post, my goal is not to try to stir up controversy. I was actually very hesitant to write this, because I don't want to interfere with somebody else's plugin sales, and I don't want to incite a witch hunt or anything like that. But at the same time, I do think that this is important information that people should know about, and I've never actually seen it mentioned before. Also, please do not ask me how to de-obfuscate plugins, and please do not discuss methods of de-obfuscating plugins in this thread.
So this community has already seen a lot of debate about code obfuscation, to the point where the topic has seemingly already been beaten to death. But for some reason, I've never actually seen anybody bring up the biggest concern that I've always had about obfuscating plugins: the performance impact.
There are different ways that one can obfuscate code. More minor forms of obfuscation tend to have little to no negative performance impact. But there are also some more aggressive means of obfuscation, that can easily cut the performance of your code in half (or worse). If you're writing a website, or a simple web application, or something else that's not really performance critical, then there's probably not any issue with using the latter type of obfuscation. But if you're writing code for a game engine... it's generally considered to be very ill-advised to intentionally reduce the performance of your code to such a high degree.
Unfortunately, the obfuscation method that I have seen being used by some very ubiquitous plugin developers is actually that latter (aggressive) form of obfuscation. You might be thinking: "Who cares? There's no way it makes *that* big of a difference." Well here, let me show you a quick example of how much of a difference it can actually make:
To summarize what you saw in that video, I used VisuStella Weather Effects to run a stupid amount of weather effects at the same time. Then, without changing anything else, I swapped the plugin out for a de-obfuscated version and ran the exact same weather effects. With the obfuscated version, I was averaging around 27-ish FPS. With the de-obfuscated version, I was getting a solid 60 FPS (and it possibly could have gone even higher, but it was capped due to VSync). That means that I more than doubled my FPS simply by de-obfuscating that one plugin. Another way to say it is that the obfuscation of that plugin was literally cutting my FPS in half (or worse).
Now you might be thinking: "Who cares? It's probably just an issue that's specific to Weather Effects, and I don't use that plugin anyway." Unfortunately, that's not the case. For those who don't know how plugins work in RPG Maker, I'll kinda summarize it. A plugin works by overwriting parts of the original engine. So when you install a plugin, you're overwriting chunks of your engine with that new code. So when you install a bunch of plugins with code that is sub-optimal, then you're essentially scattering doodoo all over your game engine. And unfortunately, with the method that VisuStella chose to obfuscate their plugins, it's pretty much impossible for their code to *not* be sub-optimal. I'll go ahead and explain some more tests that I have conducted, in case you want more examples, but I'll put it in a spoiler tag so that you can easily skip it if you don't.
I made a benchmark project (in MZ) that conducts a series of tests, using VisuStella's Events and Movement Core as its sole plugin (I left all parameters on their default values). I was using it for the sake of its Event Spawning and Self Variable functionality. It's probably not the most professional benchmark in the world, but I do think that there is significance to be found in the results that it yielded. It contains four different stress tests:
Events and Movement Core Obfuscated
Test 1: 181
Test 2: 473
Test 3: 330
Test 4: 238
Events and Movement Core De-Obfuscated
Test 1: 365
Test 2: 1051
Test 3: 707
Test 4: 470
As you can see, once again, simply de-obfuscating the plugin pretty much doubled performance in each test. A less optimistic way to say it is that obfuscating the plugin cut its performance in half.
I also ran one more benchmark, just out of curiosity, and it's not directly related to the topic of this post, but I found it interesting so I'll share it anyway. I decided to see what would happen if I took out VisuStella Events and Movement Core all-together, and instead used Galv's Event Spawner to spawn the events and Yanfly's Self Switches and Variables to handle the self variables. Here are the results of that:
Galv and Yanfly
Test 1: 767
Test 2: 7287
Test 3: 1650
Test 4: 755
As you can see, the Galv + Yanfly combo actually outperformed even the de-obfuscated plugin by quite a bit. I would assume that the reason for this difference is related to the fact that Events and Movement is a "super core" plugin that contains all kinds of other functionality that the Galv + Yanfly plugin doesn't have. So on one hand, it's not a fair comparison. But on the other hand, it's actually a pretty important comparison, because it illustrates that even though I wasn't trying to use any of that other functionality in the test, it still had a profound impact on the tests. So I guess what I'm saying is that you should maybe be careful about using a massive plugin when you actually only need a small percentage of the functionality that it offers. There is a potential cost for having that other functionality present, even if you aren't using it. This is especially true if said plugin is obfuscated, because then that cost is being doubled. The results of test #2 are especially concerning, since that is the test that involves static events that are just standing there, doing absolutely nothing at all.
--Btw, if anybody really wants it, I don't mind sharing the project files that I used to conduct these tests. However, I can't actually include any of the plugins inside that file, due to their ToS... so you'd have to get the plugins yourself and put them in there. But unless you know how to de-obfuscate the plugin, you can't really conduct a comparison, so I don't suppose that my project files would really serve you any purpose.
- The first test continually spawns parallel events onto random coordinates of the map, which each parallel event continually firing off random animations at short, random intervals. The idea was to try to make the test force as much graphics/audio processing as I could.
- The second test continually spawns events that do nothing onto random coordinates of the map. The events contain an actor sprite, but are otherwise empty (no movement route, no event commands, action button trigger).
- The third test spawns parallel events that randomly walk around on the map, while generating some random numbers into self variables, for no particular reason.
- The fourth test spawns parallel events that stand still, while generating a bunch of random numbers into self variables and doing a bunch of math on those random numbers.
Events and Movement Core Obfuscated
Test 1: 181
Test 2: 473
Test 3: 330
Test 4: 238
Events and Movement Core De-Obfuscated
Test 1: 365
Test 2: 1051
Test 3: 707
Test 4: 470
As you can see, once again, simply de-obfuscating the plugin pretty much doubled performance in each test. A less optimistic way to say it is that obfuscating the plugin cut its performance in half.
I also ran one more benchmark, just out of curiosity, and it's not directly related to the topic of this post, but I found it interesting so I'll share it anyway. I decided to see what would happen if I took out VisuStella Events and Movement Core all-together, and instead used Galv's Event Spawner to spawn the events and Yanfly's Self Switches and Variables to handle the self variables. Here are the results of that:
Galv and Yanfly
Test 1: 767
Test 2: 7287
Test 3: 1650
Test 4: 755
As you can see, the Galv + Yanfly combo actually outperformed even the de-obfuscated plugin by quite a bit. I would assume that the reason for this difference is related to the fact that Events and Movement is a "super core" plugin that contains all kinds of other functionality that the Galv + Yanfly plugin doesn't have. So on one hand, it's not a fair comparison. But on the other hand, it's actually a pretty important comparison, because it illustrates that even though I wasn't trying to use any of that other functionality in the test, it still had a profound impact on the tests. So I guess what I'm saying is that you should maybe be careful about using a massive plugin when you actually only need a small percentage of the functionality that it offers. There is a potential cost for having that other functionality present, even if you aren't using it. This is especially true if said plugin is obfuscated, because then that cost is being doubled. The results of test #2 are especially concerning, since that is the test that involves static events that are just standing there, doing absolutely nothing at all.
--Btw, if anybody really wants it, I don't mind sharing the project files that I used to conduct these tests. However, I can't actually include any of the plugins inside that file, due to their ToS... so you'd have to get the plugins yourself and put them in there. But unless you know how to de-obfuscate the plugin, you can't really conduct a comparison, so I don't suppose that my project files would really serve you any purpose.
Hopefully by this point, you understand that the code obfuscation really is coming with a non-negligible performance cost. But you might be wondering why. What could it possibly be doing that is causing it to hurt performance to such an extent? Well, I'll try to explain it, but I also need to try to keep it vague, because I don't want to accidentally spur a discussion about how to actually de-obfuscate the code:
So here is an example of an obfuscated line of code. It wouldn't actually look exactly like this in the file though:
Basically,
So the original code was simply checking the value of a Boolean property, yet the obfuscated version of the code is calling 8 functions that do a bunch of stupid nonsense and *then* it's checking the value of the Boolean property. So it's impossible for there to *not* be a performance penalty. Obviously, doing 8 things and then doing 1 thing is going to take longer than just doing the 1 thing straight up.
And it's not just one line of code where this is happening. Literally every single occurrence where a property or method of an object or class is being referenced is replaced with a chain of function calls, and every single string is being replaced with a chain of function calls. This means that it applies to almost every single instruction in the code. The reason that the code performs like dookie is because it's constantly calling functions that are completely unnecessary to the actual functionality of the plugin, some insane number of times every millisecond.
In addition to that, the fact that probably 90% of the code is essentially having to be decrypted at run-time is probably also blocking the code from being able to benefit from some performance optimizations that the JavaScript compiler would have otherwise made beforehand. But on that point, I'll admit that I'm not particularly knowledgeable about the inner workings of the V8 Engine, so I'm just assuming.
In addition to the function calling thing, they have also scattered some superfluous dummy code throughout the plugins. I.e. allocating new variables for no reason, doing weird conditional statements for no reason, etc. But honestly, the string decryption thing is really the biggest performance killer.
JavaScript:
if (!VisuMZ[decrypt(0)][decrypt(230)][decrypt(77)][decrypt(1337)]) return;
Basically,
decrypt()
(it wouldn't actually be named this) is a function that takes an integer argument, performs some operations on it to transform it into a different integer, and then passes it to yet another function, which then uses that integer to return a string from an array of strings. Both of those functions may or may not also do some other irrelevant nonsense (at a performance cost, of course) to try to confuse you. The above line of code is calling decrypt() 4 times, and decrypt() is also calling yet another function each time. This means that that one line of code is calling 8 functions. Now here is an example of what the original line might have looked like:
JavaScript:
if (!VisuMZ.SuperPlugin.Settings.Options.AddSuperManOption) return;
So the original code was simply checking the value of a Boolean property, yet the obfuscated version of the code is calling 8 functions that do a bunch of stupid nonsense and *then* it's checking the value of the Boolean property. So it's impossible for there to *not* be a performance penalty. Obviously, doing 8 things and then doing 1 thing is going to take longer than just doing the 1 thing straight up.
And it's not just one line of code where this is happening. Literally every single occurrence where a property or method of an object or class is being referenced is replaced with a chain of function calls, and every single string is being replaced with a chain of function calls. This means that it applies to almost every single instruction in the code. The reason that the code performs like dookie is because it's constantly calling functions that are completely unnecessary to the actual functionality of the plugin, some insane number of times every millisecond.
In addition to that, the fact that probably 90% of the code is essentially having to be decrypted at run-time is probably also blocking the code from being able to benefit from some performance optimizations that the JavaScript compiler would have otherwise made beforehand. But on that point, I'll admit that I'm not particularly knowledgeable about the inner workings of the V8 Engine, so I'm just assuming.
In addition to the function calling thing, they have also scattered some superfluous dummy code throughout the plugins. I.e. allocating new variables for no reason, doing weird conditional statements for no reason, etc. But honestly, the string decryption thing is really the biggest performance killer.
So does this mean that you should never use obfuscated plugins in your game?
I wouldn't go *that* far. Personally, I do use some VisuStella plugins. It is worth noting that most of my tests were being conducted under unrealistically extreme situations, so it doesn't necessarily mean that using an obfuscated plugin is absolutely going to ruin your game. You're probably never going to need to have more than 180 parallel events spamming random spell animations all over your map at any given time.
But on the other hand, it is important to note that I was only using one plugin for the tests, and I didn't have anything else going on (other than the test) at that time. In an actual game, you're going to have multiple plugins doing multiple things at any given time, and you might have all kinds of other stuff going on in your map at that time as well, so it's certainly feasible that those things could add up to create some performance issues, and heavy usage of obfuscated plugins will certainly increase the chances of that happening. Each time you add an obfuscated plugin to your game, you're overwriting more sections of your game's engine with poor-performing code.
So at the very least, I think it's important to be cognizant of the fact that there is a performance cost for adding an obfuscated plugin to your game, and to just make sure that your game can afford that performance cost, and that the functionality that the plugin provides is worth that cost. When considering using an obfuscated plugin, maybe at least make sure that you actually need/want most of the functionality that it provides. For example, if you *just* want to add self variables to your game, then maybe think twice before grabbing a plugin that does that plus 99 other things that you *aren't* looking for. In that case, it might be in your benefit to at least check for an alternative plugin.
And if you happen to be a plugin creator, I'm not trying to tell you not to obfuscate your code. That's your right, and it's not really my place to say anything about it. But I do still feel that it's important for you to be fully aware that in doing so, you *are* pushing a cost onto your customers, and onto the customers of your customers. So I would at least implore you to ask yourself if what you're gaining from obfuscating your plugins is actually worth the price that your customers/users will have to pay for it.
Well, I've kinda fizzled out and don't want to type any more at this point, so I guess I'll end things here. I do feel that I should add a disclaimer and mention that in making this post, my goal is not to try to stir up controversy. I was actually very hesitant to write this, because I don't want to interfere with somebody else's plugin sales, and I don't want to incite a witch hunt or anything like that. But at the same time, I do think that this is important information that people should know about, and I've never actually seen it mentioned before. Also, please do not ask me how to de-obfuscate plugins, and please do not discuss methods of de-obfuscating plugins in this thread.
Last edited: