+ Reply to Thread
Results 1 to 10 of 10

  Click here to go to the first Rift Team post in this thread.   Thread: How efficient is the event API?

  1. #1
    Telaran
    Join Date
    Mar 2012
    Posts
    72

    Default How efficient is the event API?

    Hi,

    I'm currently working though some ideas on how to allow my healing frames to be more customizable.

    One thing that's struck me is that currently I have a bunch of code that routes updates for changes to health, mana, power, and many other things from the incoming Events from the game, into the displayed panels for players. The displayed panel objects then push the updates through to the relevant ui pieces, this requires code to be added if I want to change routing, eg so that absorb changes can be a bar, rather than a border frame.

    It may also mean that some code is called that never actually displays anywhere, eg if you turn off power bar display the code still calls every panel object to update it, which may then discard it.

    What I'm planning to do is change things around so that as part of the improved customization bars, borders, icon spots etc can hook whatever player change events they want, and something will handle the routing.

    I'm expecting I'll be writing some kind of library to make the api well defined (so that I can build the UI to change the panel layout and use the api to self-document and generate the config ui)

    It appears I've two choices for how to do the routing:
    1. a hierarchy of tables, which eventually break into a table of functions and a loop that will push the change from the event engine calling each function.
    2. a hierarchy of event ids, and use the eventing api

    Both are relatively easy to implement, however, I was wondering how scalable the eventing api is. I believe there won't be a lot in it for processing an event vs calling functions in a table.

    I believe the place that a difference might occur is the setup of the events when a player leaves/joins a raid. I don't have a list of everything I want to event, but I suspect there are 10s of events to create. If people ask for new things I'm hoping it'd be easy to add them. I suspect creating an empty table, and populating it with empty tables (to store the callback functions) is relatively quick.

    I plan to hide it all behind an internal api anyway, so can change the implementation if a deficiency comes up, but I'm wondering which is the right and efficient solution. My gut says the event API is the right one, but I've the concern on how well it'll handle bulk event creation/deletion.

    Thanks,
    Mere
    Last edited by Mere; 06-01-2013 at 04:08 AM.

  2.   Click here to go to the next Rift Team post in this thread.   #2
    Rift Team
    Join Date
    Oct 2010
    Posts
    927

    Default

    Keep in mind that events cannot be destroyed, only created. Once you make an event once, it sticks around forever.

    With that in mind, it would be perfectly reasonable to build any necessary events as soon as they may be recognized as necessary, even before the player is in a raid, and just leave them around permanently. They don't use a lot of memory and use near-zero CPU overhead (just a little extra garbage collector time).

  3. #3
    RIFT Community Ambassador the_real_seebs's Avatar
    Join Date
    Jan 2011
    Posts
    16,859

    Default

    It may be useful to distinguish between the creation of an "event" in the sense of "a new kind of event that things can be registered to" and the creation of an "event" in the sense of "a specific thing happening right now".
    You can play WoW in any MMO. You don't have to play WoW in RIFT. Oh, and no, RIFT is not a WoW clone. Not having fun any more? Learn to play, noob! I don't speak for Riftui, but I moderate stuff there. Just came back? Welcome back! Here's what's changed. (Updated for 2.5!)

  4.   This is the last Rift Team post in this thread.   #4
    Rift Team
    Join Date
    Oct 2010
    Posts
    927

    Default

    Quote Originally Posted by the_real_seebs View Post
    It may be useful to distinguish between the creation of an "event" in the sense of "a new kind of event that things can be registered to" and the creation of an "event" in the sense of "a specific thing happening right now".
    Ah, yeah, that's fair. Creating a new event handler type means that the event handler sticks around forever. Merely triggering an event is quite cheap and doesn't result in any garbage collector issues.

  5. #5
    Telaran
    Join Date
    Mar 2012
    Posts
    72

    Default

    Ok, so some of this starts to make sense.

    Re-reading the api docs, I've a few things I want to confirm (although experimentation will show if they work)

    Firstly the Event tree is just a set of tables and can be treated as such? So if I create some events like:
    Event.MHF.PlayerEvents.Unit1.Health
    Event.MHF.PlayerEvents.Unit1.Mana
    Event.MHF.PlayerEvents.Unit2.Health
    Event.MHF.PlayerEvents.Unit2.Mana
    Event.MHF.PlayerEvents.Unit3.Health
    Event.MHF.PlayerEvents.Unit3.Mana

    Is passing parts of the tree around allowed, eg:

    myPlayerEventTable = Event.MHF.PlayerEvents.Unit3
    callsomeEventRegisterFunc(myPlayerEventTable)

    function callsomeEventRegisterFunc(eventTable)
    Command.Event.Attach(eventTable.Health, someFunc, "Player Health Changed)
    end

    expected to work?

    Can I also reset all the events by iterating the table contents? Getting the list of each handler and detaching them.

    This may seem obvious but most events seem to be global, and so are generally hooked by their full Event name (even thought they're just tables), in this case I want a set of events for each unit I'm tracking, and the ability to reuse the table.

    I'll probably find out as I experiment with these changes, but want to make sure I'm not chasing something that is never expected to work.

    Thanks,
    Mere

  6. #6
    Rift Disciple
    Join Date
    Jan 2011
    Posts
    147

    Default

    Personally, I would create a a single set of events, Health and Mana, and these events would provide an additional parameter when calling the handler function that indicates which unit this particular firing of the event is for.

    It does mean that a user can only register for Health and Mana events for all units, they have to whatever filtering they need in their handler functions.

  7. #7
    Telaran
    Join Date
    Mar 2012
    Posts
    72

    Default

    I see what you're saying, but I don't think it's the right solution for what I'm doing, as the performance wouldn't be that good. As every change in health would hit all the listening handlers which then compare the unitid.

    So I'd rather move the logic up a layer, and worked out the unit that needs an update and target that update to the things that truly want it.

    Eg the code for a health bar update only really cares about the new value for the unit it's watching. With your solution that code also needs to filter (or an small function wrapper to filter). And worse, all the handlers for health (in the simple case of 20 units) get called, so each health update has 20 tests, and only 1 of which cares, but that multiplies out with more panels, but also different data being displayed. It'd become a lot of tests, which while quick, aren't as slick as I'd like.

    By filtering higher up (with a table) I can do one code path that either gets a set of events or not, and then kick the event I need, very targeted at those pieces that care.

    Right now my code isn't so simple I've tables of unitids, which then have a table of panels for each unitid. The code then loops over those panels calling the relevant update function, it's all a bit messy, and means that the panel code also ends up in the update path, and routes updates to the bars, rather than the calls going directly to the bars that care.

    Ideally what I want to do is take the event from the game (which gives a table of unit ids and new values) split that out to call the event handler for each unitid, those events are quickly processed by the relevant UI piece to update on screen with the least amount of processing to get there.

    This also allows flexibility in that I can allow people to configure bars as they like and for whatever they like. Eg if someone has a reason to care about their range to tanks and want a bar to show it, they can configure it.

    It also means that if I wanted to display health not as a bar, but some other format I would just hook that event, rather than having to replumb the panel code to allow it to happen. Or they want absorb as a bar instead of mana. There are quite a few things I'm hoping this rework would achieve, but I'm wanting to get it right, so it'll scale out as people ask for more features.

    (I'm hoping that explains my reasoning, and that I'm not just dismissing your suggestion without thought)

  8. #8
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Quote Originally Posted by Mere View Post
    I see what you're saying, but I don't think it's the right solution for what I'm doing, as the performance wouldn't be that good.
    Do I smell premature optimization?
    In all honesty, you can only make such a claim after doing some profiling and knowing whether it's really necessary. I saw people spent ages reactoring and optimizing something for a performance gain that was barely measurable.

    Besides, I'm pretty sure the impact of the event system on the overall addon performance (any that does serious work) is just a drop in the ocean.
    Author of the Imhothar's Bags addon.

  9. #9
    Telaran
    Join Date
    Mar 2012
    Posts
    72

    Default

    I'm aware that profiling is the right way to find issues, however, given the rift api doesn't provide useful profiling, it mainly leaves me with making efficient design choices as the main option.

    At the moment I know I have a mess with routing data, I want to make it cleaner and efficient. making it so any health change for an unit I'm monitoring triggers a bunch of tests that the unit id is the one they're watching seems lazy when I can make an event that it just for that unit.

    I'm also wondering about the issue of data separation, why does a UI control need to know about the unitid? all it should care about is looking pretty and displaying the right data. So I'm hoping to achieve a degree of separation there as well.

    Perhaps I am paranoid about performance, but with unit frames being on-screen and in the action for raiders, and that's when most of the events are firing, I want to make sure that I don't impact the frame rate, and have the watchdog bark at me. So when I do need to burn cycles I have them to burn.

    (caveat, in my day job I diagnose performance problems in my company's software. I expect my dev team to produce software that performs at scale, I have the same expectation for software I produce)

  10. #10
    Rift Disciple
    Join Date
    Jan 2011
    Posts
    147

    Default

    I noticed that Zorba's LibUnitChange actually registers global events with unit IDs in the path to the event, so maybe that is the way to go.

+ Reply to Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts