Code Optimization Rules Of Thumb

AshmerAshmer Barefoot AdventurerLifeMember Posts: 1,095 ✭✭✭✭✭
So, in the work I've been doing with Oasis recently, especially optimizing and getting it cleaned up for open-source use, I keep noticing little themes and rules of thumb pop up repeatedly. This especially holds true for making the different modules modular and easy to update later on, but have also included things to just make building simple functions easier as I go.

Things like:

If you find yourself using the same block of code across multiple functions, write a function for it.

If you're going to refer to a global (especially namespaced) variable more than once in a function, load it into a local variable.

Save useful code that other people wrote.

--

What are some coding rules of thumb you've found? (Admin included!)

the way she tells me I'm hers and she is mine

open hand or closed fist would be fine

blood as rare and sweet as cherry wine

Comments

  • TrigruTrigru the Bumberton's DelightMember Posts: 255 ✭✭✭✭
    edited September 2014
    Ashmer said:

    What are some coding rules of thumb you've found? (Admin included!)

    A Rapture block, just for you.

    function should_i_rewrite_this(block) { local creation_year, written_by; if !valid_function(block) and !valid_subroutine(block) then { return; } creation_date = get_year_code_was_written(block); written_by = get_code_creator(block); if written_by = search_persona("ivoln") then { return 1; } else if creation_year >= 2011 and (written_by = search_persona("razmael") or written_by = search_persona("oleis")) then { return 0; } else if creation_year >= 2007 then { (* All old code can just go die *) return 1; } else if creation_year < 2007 then { return "YEAH BETTER NOT"; } return 0; }

    Produces an error if returning a string, which is a totally accurate representation of old code.
    image
    AshmerDrahkunaXenia
  • TozToz Member Posts: 2,568 ✭✭✭✭✭
    Pseudocode first. I thought it was dumb and a waste of time until I tried it. I wrote my offense in one go by talking through it, then outlining every case I care about then a general catchall, and only then did I start coding.
    TrigruAshmerIshin
  • SetneSetne The Grand Tyrant Member Posts: 835 ✭✭✭✭✭
    If you're not going to use a variable outside of a code block/function, make sure it's local.

    Make sure all code is properly spaced to make it more easily read.

    In the event of an error, drop a bunch of echo's and such between code blocks to see where things are going wrong.

    Learn Ruby.

    Ingram said:
    "Oh my arms are suddenly lubed"
  • AshmerAshmer Barefoot Adventurer LifeMember Posts: 1,095 ✭✭✭✭✭
    @Trigru, that is both fascinating and frightening all at once.

    Also, system building things I just remembered that have been stewing in my brain:

    Build modules or distinct sections of code for a specific purpose. Example: Character database module (core functions, aliases, triggers), defense scripts, curing scripts.

    Avoid using string comparisons with specific game data for code - use data entries that can be easily found and rewritten instead.

    Have every module or distinct section of code be as self-reliant as possible, and if at all possible, only called up in ONE other place.

    Avoid namespace poison - keep all of your core global tables in one central location and one standardized location across all modules.

    If a function can't or shouldn't perform its specific function, have it return nil early in the script.

    For Mudlet, avoid using Events as much as possible. Great idea, but super process-heavy. Not even necessary for open-source systems, except for things like sysOnLoad and sysDownloadEvent.

    Also, 3,423,562,174x on @Toz's comment: superior logic implemented trumps superior code 100% of the time.

    the way she tells me I'm hers and she is mine

    open hand or closed fist would be fine

    blood as rare and sweet as cherry wine

    Ishin
  • IrruelIrruel Member Posts: 670 ✭✭✭✭
    If you have a table, such as:
    vensToAffs = {
    curare = "paralysis",
    aconite = "stupidity",
    }

    And sometimes, you want to know the reverse, i.e. what venom to use to deliver paralysis, then instead of looping through the table every single time you ever want to envenom, just loop through it once at startup and create the reverse table.

    affsToVens = {}
    for ven,aff in pairs(vensToAffs) do
    affsToVens[aff] = ven
    end

    Take the time to create the right tables for the information you need, and a huge part of your processing becomes simple table lookups.


  • AshmerAshmer Barefoot Adventurer LifeMember Posts: 1,095 ✭✭✭✭✭
    edited January 2015
    Parentheses! Consider, if you will, two different versions of the same function.

    One:

    function focus()
    return o.bals.focus
    and not tmp.paused
    and not (affs.current.impatience
    and not affs.attempted.impatience)
    and not affs.current.stun
    and not (affs.current.asleep
    and not affs.attempted.asleep)
    and not affs.current.unconscious
    end

    Two:

    function focus()
    return o.bals.focus
    and not (tmp.paused
    or (affs.current.impatience
    and not affs.attempted.impatience)
    or affs.current.stun
    or (affs.current.asleep
    and not affs.attempted.asleep)
    or affs.current.unconscious)
    end

    One of these items causes Focus to spam off-balance on every prompt. The other doesn't (hopefully, reproducing the scenario is hard).

    the way she tells me I'm hers and she is mine

    open hand or closed fist would be fine

    blood as rare and sweet as cherry wine

  • AshmerAshmer Barefoot Adventurer LifeMember Posts: 1,095 ✭✭✭✭✭
    Trigru said:

    Ashmer said:

    What are some coding rules of thumb you've found? (Admin included!)

    A Rapture block, just for you.

    function should_i_rewrite_this(block) { local creation_year, written_by; if !valid_function(block) and !valid_subroutine(block) then { return; } creation_date = get_year_code_was_written(block); written_by = get_code_creator(block); if written_by = search_persona("ivoln") then { return 1; } else if creation_year >= 2011 and (written_by = search_persona("razmael") or written_by = search_persona("oleis")) then { return 0; } else if creation_year >= 2007 then { (* All old code can just go die *) return 1; } else if creation_year < 2007 then { return "YEAH BETTER NOT"; } return 0; }

    Produces an error if returning a string, which is a totally accurate representation of old code.
    Funny story, @Trigru, I can actually read that now for some reason. I couldn't follow it when I looked at it before.

    the way she tells me I'm hers and she is mine

    open hand or closed fist would be fine

    blood as rare and sweet as cherry wine

    Ishin
  • OleisOleis Producer Emeritus Member, Administrator, Immortal Posts: 1,392 admin
    It would only be realistic Rapture if all the variables were named things like temp2 and we used player to represent persona and p to represent player.

    (On that note, I'm going on vacation <3)
    You say to Slyphe, "You're so freaking smart."
    [---]
    "^," Slyphe agrees with you.
    RiluoTragerIshin
  • AshmerAshmer Barefoot Adventurer LifeMember Posts: 1,095 ✭✭✭✭✭
    ... Oh dear God. That's like cleaning out Serenity's old tmp namespace on crack.

    Have a good vacation!

    my thread was oleis' last post before he left on vacation squeeeee

    the way she tells me I'm hers and she is mine

    open hand or closed fist would be fine

    blood as rare and sweet as cherry wine

  • DrahkunaDrahkuna Member Posts: 44 ✭✭
    Because of the way Lua is interpreted, variable access is quickest when you're using local variables. Then comes external locals and, lastly, globals.
    Local variables are external when they're declared inside of a function, so to make your code even quicker, try to declare your locals outside of function calls.
  • IrruelIrruel Member Posts: 670 ✭✭✭✭
    What do you mean by declaring them outside of function calls?


    function something()
    local taffs = pvp.affs
    local a_esult = false
    for aff,pres in pairs(taffs) do
    something
    end
    return a_result
    end

    That would be 2 external locals in that function, according to your explanation. What would be an internal one?





  • DrahkunaDrahkuna Member Posts: 44 ✭✭
    local taffs = pvp.affs
    function something()
    for aff, pres in pairs(taffs) do ...
    end




  • DrahkunaDrahkuna Member Posts: 44 ✭✭
    Ash makes good use of them in his system modules. The further into the function's scope you go, the slower access becomes. If I were to declare taffs within the for loop for some reason or another, it would be process more slowly than outside of the loop.
  • IrruelIrruel Member Posts: 670 ✭✭✭✭
    edited January 2015
    Hrm. The only way I can see that working is if creating the local var (which is just a reference) persists and is available to any function, but still has speed advantages of being a local var.

    If that's the case, why does anyone ever use anything but locals? What's the advantage of a global variable? Why wouldn't I just do:
    local pvp = {}
    and then just treat pvp like it's a global variable, but with the speed advantages of a local?

    edit:
    What I mean to ask is, if a system (say tripwire for the sake of argument) used these global namespaces:
    tw = {}
    pvp = {}

    Could I speed up the entire system just by going to the very beginning, where pvp and tw are declared, and change them to:
    local tw = {}
    local pvp = {}

    ?



  • DrahkunaDrahkuna Member Posts: 44 ✭✭
    As soon as the variable's of no use, it's freed up and the reference wouldn't work anymore. I see what you're getting at, though. http://lua.org/gems/sample.pdf
  • DrahkunaDrahkuna Member Posts: 44 ✭✭
    The bit under Performance Tips explains it better than I can. Do a search for math.sin if you're short on time.
Sign In or Register to comment.