Moving notetag reading in Yanfly plugins

Discussion in 'Javascript/Plugin Support' started by Galenmereth, Nov 29, 2015.

  1. Galenmereth

    Galenmereth I thought what I'd do was Veteran

    Messages:
    2,206
    Likes Received:
    1,905
    Location:
    Norway
    First Language:
    English
    Primarily Uses:
    RMMV
    This is related to the following and later / some earlier posts on this topic in the original Yanfly plugin's thread: http://forums.rpgmakerweb.com/index.php?/topic/48860-yep-yanfly-engine-plugins-newest-armor-scaling-plugin-count-33/?p=511130
     
    Long story short, I'd like to see data reading logic moved out of DataManager.isDatabaseLoaded() because this function is designed to be used only to read the status of the loading of the database objects (the $data* objects). This function can and is called repeatedly by the core scripts to wait for the startup scene (Scene_Boot) to be done loading these data objects before proceeding. Other plugins may also need to check this to ensure that these objects are available before they run their own logic, especially if it's logic to be run at startup.
     
    The current implementation in the YEP series of plugins means that notetags are read and processed over and over when this function is called, which is both unnecessary and breaking with the design behind the function.
     
    I propose changing this code starting on line 576 of latest YEP_CoreEngine.js (it's also used in other plugins, but I use this for the example):

    Yanfly.Core.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;DataManager.isDatabaseLoaded = function() { if (!Yanfly.Core.DataManager_isDatabaseLoaded.call(this)) return false; this.processCORENotetags1($dataItems); this.processCORENotetags1($dataWeapons); this.processCORENotetags1($dataArmors); this.processCORENotetags2($dataEnemies); this.processCORENotetags3($dataActors); this.processCORENotetags4($dataClasses); return true;};Into this:

    Yanfly.Core.DataManager_onLoad = DataManager.onLoad;DataManager.onLoad = function(object) { Yanfly.Core.DataManager_onLoad.call(this); if (this.isDatabaseLoaded()) this._processYanflyNotetags();};DataManager._processYanflyNotetags = function() { this.processCORENotetags1($dataItems); this.processCORENotetags1($dataWeapons); this.processCORENotetags1($dataArmors); this.processCORENotetags2($dataEnemies); this.processCORENotetags3($dataActors); this.processCORENotetags4($dataClasses);}The benefits of this change are:

    • DataManager.isDatabaseLoaded() contains only the function of checking whether the database objects have been loaded, its original and only logical role to have.
    • Notetags are only read once, but they are just as guaranteed to load correctly now as before this change.
    • The tentatively named DataManager._processYanflyNotetags function can easily be extended by other Yanfly plugins to read additional data, while encapsulating this logic in a clearly defined and separate function space.
    • We do not extend Scene_Boot, which Yanfly explicitly said he did not want to touch.

    I created this topic to discuss this change. If there are problems with it we can discuss it and find the best solution that solves the issues that may exist with it. I'm not here saying one way is better than all others, just that the current implementation is something I find very problematic for reasons I have already described ad nauseam.

    Let's find the best solution together :)
     
    #1
    Goldstorm, Amysaurus, Quxios and 2 others like this.
  2. ??????

    ?????? Diabolical Codemaster Veteran

    Messages:
    6,264
    Likes Received:
    2,310
    Location:
    Your OS
    First Language:
    Binary
    Primarily Uses:
    RMMV
    I think the best approach would incorporate a 'core note reading' function. Because if you have 50 plugins, and each of them is doing a similar function for loading their notetags, then you are repeating your code over and over, which is generally considered bad practice in programming.

    It would be easy enough to have a single 'read notetag' function that parses a string for some tag, and then stores the desired value from said tag in the desired variable. The MVCommons note reading function is a perfect example on how to do such a parsing function:

    /** * MVC.getTag(text, tag, defaults) * @param text The text where you want to search for. * @param tag The name for the tag * @param defaults [optional] an object containing default values if they are not found. * @return an object containing params and text field. * @note params is an array with indexed values after : 1, 2, 3... * @note text is the text inside <tag></tag> * @note tags are case insensitive. * * Gets a value from any of the following versions: * <tag: param1, param2, param3, param4, ...>text</param> * <tag: param1, param2> * <tag>text</tag> * <tag> */ function getTag(text, tag /*, defaults */) { var result = arguments.length > 2 ? $.shallowClone(arguments[2]) : {}; var match; result.text = result.text || null; result.params = result.params || []; var txt = '(([^<]*?))'; var param = '([ \t]*([^>]*)[ \t]*)'; var param_cont = '(\s[ \t]*,\s[ \t]*' + param + ')*'; var param_list = '(' + param + param_cont + ')?'; var open_tag = "<" + tag + '([ \t]*?\:[ \t]*?' + param_list + ")?[ \t]*>"; var close_tag = "</" + tag + ">"; match = text.match(new RegExp(open_tag + '(' + txt + close_tag + ')?', "im")); if (!match) { return null; } result.text = match[9] || result.text; if (match[2]) { result.params = match[2].split(',').map(function (i) { return i.trim(); }); } return result; }Then within the aforementioned 'core note reading' function, you would alias it for a new plugin, to look somewhat like this:

    function CoreNoteReader(databaseItem){ databaseItem.desiredVariable = getTag(databaseItem.note, /<notetag: value>/); };My reason for suggesting having a core note reading function, is because of the volume of people that use more than 1 yanfly plugin in their project. Its fairly high, so I dont think it is really too much to ask them to have the notetag parsing script - or to include it in the core script.

    Additionally, by using this approach, you are not repeating the parsing logic over and over.
     
    #2
    Goldstorm likes this.
  3. Yanfly

    Yanfly Developer

    Messages:
    1,696
    Likes Received:
    2,314
    With a small fix of

    Yanfly.Core.DataManager_onLoad.call(this);

    to

    Yanfly.Core.DataManager_onLoad.call(this, object);

    That's a bit better and a change I can work with and I'll be spending the rest of the night updating my plugins to try it out. See edit below.

    [​IMG]

    That said, I'll keep my word from what I said in the past to Dekita:

     

    I'm not a difficult person to work with and willing to make improvements. However, things must be logical in order for me to accept them (can you fault me for that?). This was all that was needed to be shown for me in order for me to make a change.

    EDIT:

    On second thought, hold the phone.

    In the process of loading up a new map, the function is ran again:

    [​IMG]

    While I can make a check to stop it once loaded, I'm going to ask, is that within the scope of "Good Practice" seeing as how this is a discussion for standards of programming here.
     
    Last edited by a moderator: Nov 29, 2015
    #3
    ?????? likes this.
  4. KockaAdmiralac

    KockaAdmiralac Cube-shaped garbage can Veteran

    Messages:
    570
    Likes Received:
    156
    Location:
    Belgrade
    First Language:
    Serbian
    Primarily Uses:
    N/A
    I still don't understand why are you loading notetags on database load, and not in-game...

    That's what happened in YEA scripts, also, where just simple edits would stop overaliasing DataManager.loadDatabase

    Am I missing the whole point?
     
    #4
  5. Yanfly

    Yanfly Developer

    Messages:
    1,696
    Likes Received:
    2,314
    You can start reading from this post onward to see how I came to my conclusion today. I'm not really in the mood to discuss it for the nth time.
     
    #5
  6. KockaAdmiralac

    KockaAdmiralac Cube-shaped garbage can Veteran

    Messages:
    570
    Likes Received:
    156
    Location:
    Belgrade
    First Language:
    Serbian
    Primarily Uses:
    N/A
    Hmmm... OK, looks like I started reading from this post (@Galenmereth linked to it), and completely missed the point why extractMetadata wouldn't do it's job correctly.

    But I still don't understand one thing.

    Why are you loading it on database load, and not somewhere later?

    Like, let's suppose your actor is walking on a map and you have a notetag that tells you is he moving by 1 or 2 spaces. (it would be a very stupid plugin, but nvm)

    So, your actor notetag is like this :

    <MoveSpeed:10>And, now you can do this.

    In method where player is moving (Game_Player.prototype.moveStraight?) you will access your note for the first time. You can access it in two ways : 

    1)

    moveby($gameParty.members()[0].actor().note.meta.MoveSpeed) // this doesn't exist, but whateverThat is the solution when you want to use metadata, which you most probably don't because if your notetag is like this :

    <MoveSpeed>10</MoveSpeed>It wouldn't extract it at all.

    2)

    if($gameParty.members()[0].MoveSpeed === null) // or undefined{    $gameParty.members()[0].extractMoveSpeed();}moveby($gameParty.members()[0].MoveSpeed)And in extractMoveSpeed you are extracting your notetags.

    I know this will bug more, but that would be very, very unnoticable, just as same difference as between are you using i++ or ++i (not that small, but you got the point, right?)

    I realize how stressed you are for answering these things for Xth time (X > 999), you don't need to answer if you don't want to.

    I think I really missed the point even after reading those bunch of posts.
     
    Last edited by a moderator: Nov 29, 2015
    #6
  7. ??????

    ?????? Diabolical Codemaster Veteran

    Messages:
    6,264
    Likes Received:
    2,310
    Location:
    Your OS
    First Language:
    Binary
    Primarily Uses:
    RMMV
    well hell, if we are going down to the level of the best way to implement a loop, its this:

    Code:
    for (var i = Things.length - 1; i >= 0; i--) {  Things[i]};
     
    #7
  8. Galenmereth

    Galenmereth I thought what I'd do was Veteran

    Messages:
    2,206
    Likes Received:
    1,905
    Location:
    Norway
    First Language:
    English
    Primarily Uses:
    RMMV
    @Yanfly: My bad, I managed to overlook that loadDataFile() was used for the map files too, which of course means it runs the whole shebang again. I wonder, is it too late in the process to extend createGameObjects() instead, like so?

    Yanfly.Core.DataManager_createGameObjects = DataManager.createGameObjects;DataManager.createGameObjects = function() { Yanfly.Core.DataManager_createGameObjects.call(this); this._processYanflyNotetags();}This is run at the start of setupNewGame(), setupBattleTest() and setupEventTest(), before the scene transition starts. I'm still not entirely happy about the placement and I think it'd be better to place it in a dedicated spot in Scene_Boot, but if you have to avoid it this is an improvement. But it does make more sense to place it within createGameObjects() over isDatabaseLoaded(), since notetags can and do modify game objects. This will also just run once. In Scene_Boot it's called in the start() function, and thus only after the database is indeed loaded, too.
     
    #8
  9. Yanfly

    Yanfly Developer

    Messages:
    1,696
    Likes Received:
    2,314
    I don't use extractMetaData because it's inflexible, is case sensitive, and while useful and handy for newcomers, is not user friendly for the end users (ie. not the scripter). Plus, I cannot do complex notetags with it to parse the data I'd like to.

    As for my decision to load notetags at the very beginning, I believe that all $dataEntries should be finished loading with their data from the beginning rather than having their notetag data parsed mid-game as this can cause lots of problems. Commercial games in the past have loaded their data mid-game and it becomes very noticeable and buggy (Ar Tonelico 2 for example) in addition to laggy. That's the reason I don't do it anywhere later other than on Database Load.

    DataManager.onLoad, however, would have been ideal except it'd require running a check every single time a map is changed (which can be very often depending on the project). As the whole "ordeal" was brought to my attention because it was considered "bad practice", I equally think it's just as much of "bad practice" (if not more) to require a check each time a map is loaded.

     

    DataManager.createGameObjects() runs each time a new game is started, loaded, battle tested, etc. The flaws I can see with this are:

    1. It'd still end up getting ran multiple times depending if the player is to restart the game and choose to start a new game or load a new game (especially if the game type is one that prompts save scumming).

    2. Unlike DataManager.isDatabaseLoaded(), createGameObjects actually does have a semi-high likelihood of being overwritten (as per Tomoaki, a JP scripter that prefers to make shmups, platformers, and puzzle games with RPG Maker instead of... RPG's).

    I know I'm sounding difficult here, but these were possibilities I've considered before.

     

     

    Try this: it's the fastest loop:

    Code:
    var i = array.length;while (i -= 1) {  console.log(i);}
     
    Last edited by a moderator: Nov 29, 2015
    #9
  10. KockaAdmiralac

    KockaAdmiralac Cube-shaped garbage can Veteran

    Messages:
    570
    Likes Received:
    156
    Location:
    Belgrade
    First Language:
    Serbian
    Primarily Uses:
    N/A
    @Yanfly

    I know that extractMetaData is stupid, because:

    MV Notetags that use metadata :<DONOTADDANYSPACEHERE:oRYOUAREADEADMAN>VXA Notetags that use regular expressions:<                                         yolo                             :                                          swag                                       >I never experienced noticeable and buggy notetag loading.

    What exactly do you think it's the problem with mid-game loading?

    Can you try to describe that buggy scene?

    Maybe the problem will also occur when loading from savefiles, but if you do it the proper way, it can be done.

    And yeah, I understand why DataManager.onLoad is a "bad practice", but if you just put it in DataManager.isDatabaseLoaded those plugins are also very noticeably buggy, because they are being loaded on game start, and, honestly, tell me would you more like a game that lowers the framerate by 1-2 FPS because of notetag loading, or bugs 2 seconds on the beginning?

    And I just can't believe that we fell down on more and more notetags even after update to MV.

    I'm tempted to make my own RM...

    EDIT: BTW...
     
    Last edited by a moderator: Nov 29, 2015
    #10
  11. Galenmereth

    Galenmereth I thought what I'd do was Veteran

    Messages:
    2,206
    Likes Received:
    1,905
    Location:
    Norway
    First Language:
    English
    Primarily Uses:
    RMMV
    1. Yeahp, that is true. I still consider it better because it doesn't have the complete unknown potential snowballing effect that isDatabaseLoaded() might have.
    2. Other plugins that completely overwrite such fundamental elements should have to take on the burden of compatibility, not vice versa. I mean, we can only speculate what others are going to overwrite.
    I have to concede that it does look like using isDatabaseLoaded() is a good solution if we absolutely must restrain ourselves and only use DataManager functions, but I really feel like we are ignoring the fact that this is fundamentally not the right approach and we ought to put the notetag reading in Scene_Boot.start(). If another plugin completely overwrites that, why not require it to be placed before yours so that you can extend Scene_Boot.start(), alias it, call the notetag parsing function and then call the aliased start function. Because that way you guarantee that

    1. All database objects are loaded
    2. It's only run on boot, and you need no internal variables to determine if notetags have already been loaded
    3. It's put in a logical place and won't interfere with other plugins
    As an example, looking at the Skip Title Screen plugin, if it were placed above YEP plugins, the Scene_Boot.start() aliasing would work fine.
     
    #11
    Yanfly likes this.
  12. Yanfly

    Yanfly Developer

    Messages:
    1,696
    Likes Received:
    2,314
    For 2. Dunno. I've worked together with Tomoaki before in the JP community before moving over to the EN communities. His soaring popularity there is pretty astounding if I must say so myself, and it's better to avoid putting that burden on any one scripter's shoulders. As I said before, how someone programs their plugin/script is no business of mine. The only thing I can do is just sit back and make things as approachable as possible as my stance is that players come before users and users come before programmers. Games shouldn't be made at the disadvantage of the player because the user was unable to find a script that somehow complied with all the best programming practices.

    Also, while isDatabaseLoaded is the solution, I've stated before that I've made two moves in the past before settling here. I know as much as you do that this isn't the most ideal location. However, the structure of RPG Maker MV's source doesn't give us much freedom and the scripting habits of the members here aren't things I want to dictate and enforce (ie thou shall not overwrite Scene_Boot.prototype.create). It's not my place. isDatabaseLoaded was the 'I have no choice' function that I ended up with.

    And yes, the change of placement of the Skip Title plugin would "fix" the issue, but once again, that puts the burden on the other scripter at hand, something I want to avoid as it's not my place.
     
    Last edited by a moderator: Nov 29, 2015
    #12
    DoubleX likes this.
  13. ??????

    ?????? Diabolical Codemaster Veteran

    Messages:
    6,264
    Likes Received:
    2,310
    Location:
    Your OS
    First Language:
    Binary
    Primarily Uses:
    RMMV
    @Kocka - The loop from the most popular answer in that thread:

    for (var i = 0, len = myArray.length; i < len; i++) {}I would have thought that  initializing two variables when only one is required would be more intensive, but i guess as its only done at the start of the loop one time, it has no real impact. As the guy has given it to performance testing, I cant really argue with that. :D

    I am gonna run some tests of my own when I get the time to compare it against my suggested approach :D
     
    #13
  14. Galenmereth

    Galenmereth I thought what I'd do was Veteran

    Messages:
    2,206
    Likes Received:
    1,905
    Location:
    Norway
    First Language:
    English
    Primarily Uses:
    RMMV
    It doesn't. As long as you alias Scene_Boot.start(), and as long as that script is placed before your scripts, problem solved. It's not uncommon to ask users to have to place plugins in specific order because no matter what we do we can't get around that in some cases.

    I fully agree MV's structure is binding our hands and feet quite a lot though. It does make it significantly challenging to be both user friendly, compatible and structurally sound.
     
    #14
  15. KockaAdmiralac

    KockaAdmiralac Cube-shaped garbage can Veteran

    Messages:
    570
    Likes Received:
    156
    Location:
    Belgrade
    First Language:
    Serbian
    Primarily Uses:
    N/A
    @Dekita

    Check this out.

    I don't really understand the results, is that Prefix + Cached the fastest?

    Why the hell are 4 answers marked as fastest?

    for(var i = 0; i < 99999; ++i) console.log("HA");console.log("!");You know the output :)
    Wouldn't it be the best if we made a community standard for reading notetags, that is NOT in DataManager.isDatabaseLoaded?

    Like, if Dekita + Yanfly + Galenmereth used DataManager.loadNotetagsHere, and some random scripter overwrote it, that would be like 1000 vs 1...
     
    Last edited by a moderator: Nov 29, 2015
    #15
  16. Yanfly

    Yanfly Developer

    Messages:
    1,696
    Likes Received:
    2,314
    I'll go ahead and say that once again, it's not me who should dictate how other people handle their scripts and plugins. Just remember that I've once mentioned before that I've used Scene_Boot.start() and decided it wasn't the proper location with all the potential conflict that may occur there.

    That said, I feel like I've done my part here by testing the alternatives you provided me and given to what I believe are logical explanations on my choice decisions to not use the respective functions. I'll see to it that I'll keep an open mind to any suggestions you may come up with as multiple minds are better than one.

    But at the moment, I don't see the need for a change as it's not intrusive to hamper the workings of other plugins and games. Should there ever arise for the need to legitimately require calling DataManager.isDatabaseLoaded() mid-game and my notetag parsing renders that project to be unplayable, I'll reconsider my choice and make the appropriate changes to my work as I deem reasonable.

    I'll be leaving this discussion, but should you find a suitable solution, do not hesitate to send me a PM. Remember that I keep an open mind and have no intentions of being difficult and willing to receive criticism.

    Thanks.
     
    #16
    DoubleX likes this.
  17. DoubleX

    DoubleX Just a nameless weakling Veteran

    Messages:
    1,456
    Likes Received:
    541
    First Language:
    Chinese
    Primarily Uses:
    N/A
    But then Yanfly would have to be sure that all those plugins can indeed be placed above his/hers. Sometimes some of those plugins can have some other compatibility issues needing those plugins to be placed below his/hers and those issues might just be as, if not more, severe. Now Yanfly would have to think which choice will lead to more compatibility issues that he/she cares about(so does his/her users as he/she cares about their needs/wants), as it's crystal clear and obvious that he/she wants his/her plugins to be as compatible to as many plugins he/she cares about(so does his/her users as he/she cares about their needs/wants).

    Also, let's clean up the discussions:

    1. Some of us think that there has to be good solutions(those conforming to good practices) to this problem, so all the bad ones(those suffering from bad practices) will be unconditionally discarded.

    2. Some of us suspect that there's indeed no good solution to this problem, so the bad ones can still be chosen if they're indeed the best ones.

    3. From what I've observed all along, good practices here refer to those ignoring the context of the problem(general programming practices), while whether a solution's best here has to be judged under the context of the problem(like, choosing between breaking compatibility due to DataManager.isDataBaseLoaded() vs those due to Scene_Boot.prototype.start(), with the addressed plugins and targeting audiences considered) and the priorities of goals to be accomplished(like valuing good practices more than user needs/wants vs the vice versa).

    4. We'll never agree on each other as long as:

    - Those insisting on having to exercise good practices that ignore the context of the problem continue to be unwilling/unable to thoroughly comprehend the context of the problem and/or work with it.

    - Those insisting on having to solve the problem conforming to the constraints imposed by the underlying context continue to be unwilling/unable to exercise good practices that ignore the context at all costs.

    5. It's entirely possible that we're actually discussing about plugin developer philosophies:

    - We all value exercising as many generally good practices(those ignoring context) as we can, and we also value getting the things done well under the context we've to work with(some of us think that we've little to no control to the context so changing it is just unrealistic, while some of us think that the context has to be changed anyway at all cost if it's proven to be preventing good practices to be exercised)

    - When there are cases where exercising some good practices will certainly lead to a more undesirable solution due to the underlying context, some of us will persist on exercising those good practices as long as the solution still works, while some of us will compromise those good practices and choose a more desirable solution under the context instead.
    On more concrete examples:

    1. Upon all the notetag loading timings we're currently exploring(choosing among all available timings is what we're discussing all along):

    - DataManager.onLoad

    - DataManager.createGameObjects

    - DataManager.extractMetaData

    - DataManager.isDataBaseLoaded

    - Scene_Boot.prototype.start

    - Scene_Boot.prototype.create

    - Scene_Boot.prototype.terminate

    - getTag in plugin MVCommons(assuming it's indeed a new timing)

    - Right before using the notetag values

    2. Some of us will choose based on good practices without considering the context of the problem, for instance(from what I've collected):

    - DataManager.isDataBaseLoaded is discarded as it'd violate its very referentially transparent(side effect free) nature, which is a vital assumption made by some other plugins.

    - Plugins rewriting Scene_Boot.prototype.start and/or Scene_Boot.prototype.create should be safely ignored as those plugin developers are solely responsible for any compatibility issue raised.

    - Using timings that are intended for loading notetags is more important that working with the constraints imposed by the context and comparing the impacts on the solution under the context among all available timings.

    - If good timings can only come by changing the underlying context, it should be changed at all costs.

    3. Some of us will choose based on the constraints imposed by the underlying context we've to work with and compromise some good practices if there's no other choice, like(in the case of Yanfly):

    - There's little to no control over the other plugins that need to be taken care of.

    - Targeting audiences' needs/wants should take at least extremely high precedence.

    - Different data types should be able to be distinguished when their notetags are read.

    - Data in some data types should be able to access those in some other data types when their notetags are read.

    - The chosen timing shouldn't be likely to be overwritten by at least most of the other plugins that need to be taken care of.

    - All notetags should be completely read before they're possible to be used by at least most of the other plugins that need to be taken care of.

    - Potentially severe performance issues due to reading notetag values right before using them should be avoided at all cost.

    - The solution should raise as few and as minor compatibility issues with at least most of the other plugins that need to be taken care of as possible.

    - Only working solutions having the best balances among all the above constaints should be chosen.
    If we're not going to put into the others' shoes(as well as all the concerns they've to care about, contexts they've to work with and good practices they've to exercise), we'll never agree with each other, as there's little to no common ground among all the above different opinions, meaning we'll probably be repeatedly stressing on our plugin developing philosophies over and over again without progressing the discussions any further.
     
    Last edited by a moderator: Nov 29, 2015
    #17
    Archeia likes this.
  18. Galenmereth

    Galenmereth I thought what I'd do was Veteran

    Messages:
    2,206
    Likes Received:
    1,905
    Location:
    Norway
    First Language:
    English
    Primarily Uses:
    RMMV
    I can only agree to disagree when a major reasoning is that one function is arbitrarily considered less likely to be overwritten compared to another. There are no stats to back it up, there is only conjecture. We are fooling ourselves if we think we can make plugins that will be compatible by guessing at what other plugin writers may or may not overwrite. It's not how it works. The problems posed by going down that route is that we change the fundamental functions of the engine (which are already problematic to begin with) and making premature hacky code jobs based on guesses and a thin attempt at more compatibility while changing the very structure of what core functionality in the engine does.

    The only reason I went this far with this topic is because I care about users and players. But I am not going to pursue it any further since dialogue has stopped. I will simply do what I can do on my end and improve what I can improve. It will be more productive than keeping this going. I've said what I wanted to say three times over to ensure no misunderstanding. The fact that it's still misunderstood means I'm wasting my time.
     
    #18
    Vegnarus and mlogan like this.
  19. DoubleX

    DoubleX Just a nameless weakling Veteran

    Messages:
    1,456
    Likes Received:
    541
    First Language:
    Chinese
    Primarily Uses:
    N/A
    Perhaps Yanfly do have such data, although I'd like him/her to expose them if he/she really have them :)

    Edit: If you really think Yanfly won't have such data, you'll either have to prove that, or it's always impossible for anyone to have any :D
     
    Last edited by a moderator: Nov 29, 2015
    #19
  20. Iavra

    Iavra Veteran Veteran

    Messages:
    1,797
    Likes Received:
    856
    First Language:
    German
    Decrement loops are actually a lot slower in general, than incrementing ones, since JS environments usually expect you to go forwards, so you will get a lot of cache misses. Also, in theory it's faster to pre-increment, than to post-increment, because incrementing afterwards creates a temporary variable to store the new state.

    So, the fastest loop would be:

    Code:
    for(var i = 0, max = ...; i < max; ++i) { ... }
    /edit: Also, if you are assigning variables inside the loop, it's faster to define them outside, so memory is only allocated once, like this:
    Code:
    var elements = _elements, element;for(var i = 0, max = elements.length; i < max; ++i) { element = elements[i]; ... }
    Note, that i'm assigning a local variable (elements) to a variable in a greater scope (_elements), since it's faster to access variables in a smaller scope. That's one of the reasons, why most of my functions start with declaring a bunch of variables and creating local references for objects in wider scopes.
     
    Last edited by a moderator: Nov 29, 2015
    #20
    Galenmereth likes this.

Share This Page