Unity Community


Page 1 of 2 12 LastLast
Results 1 to 20 of 33

  1. Location
    UK
    Posts
    232

    Is SendMessage really that bad?

    I am thinking of using the NotificationCenter code off the Wiki:

    http://www.unifycommunity.com/wiki/i...ficationCenter

    As far as simplicity of use and implementation for a message system between components, this seems unbeatable.

    Without the use of Generics, the only other code I have seen is this using Delegates:

    http://forum.unity3d.com/viewtopic.php?p=249862#249862

    However using that code requires considerably more implementation work and plumbing for every new message.

    I have seen multiple posts on the forums suggesting SendMessage is extremely slow but no information in the Documentation and no concrete examples of performance differences between SendMessage and direct calls.

    I do not want to implement public properties for calling components because during development I constantly delete and recreate objects and this mechanism is complex to manage.

    I want a notification system where the sender needs to know nothing about the receiver and this code seems perfect.

    Thanks
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  2. Location
    UK
    Posts
    232
    Well, in the absence of any hard evidence on what percentage slower a SendMessage is compared to a direct call, I am going to go with the simpler option and use SendMessage.

    I will only ever have a single script assigned to each GameObject so the fact it will try to call it on each MonoBehaviour of a GameObject should not have a performance impact.

    BTW does SendMessage require Reflection since it is calling a function based on a string name?
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  3. Posts
    6,314
    SendMessage more than likely uses Reflection, which is probably why it is so expensive. I made a very simple NotificationCenter that might suit your situation. It does the minimum amount of casting/unboxing/boxing and is super simple to add new event types. All you need to do is add a new enum. The post with the sample code and details is here:
    http://forum.unity3d.com/viewtopic.p...tart=15#249309


  4. Location
    UK
    Posts
    232
    Thanks uprise

    I've seen your other post which is what prompted me to post this one. You code isn't a million times for complex than the one on the wiki, but it is definitely more awkward to work with hence I'd prefer to use the Wiki one if possible.

    The one on the Wiki does need a few changes to work on the iPhone but I now have it working.

    Would love an answer from Unity on whether or not SendMessage is implemented via Reflection and if it does are the reflection calls cached or are they made every time?

    I noticed that the Penelope same is using SendMessage, so Unity must think its suitable for use on the iPhone.

    Thanks
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  5. Location
    The Netherlands
    Posts
    1,023
    Quote Originally Posted by steddyman
    I noticed that the Penelope same is using SendMessage, so Unity must think its suitable for use on the iPhone.

    Thanks
    You should realize that "relatively expensive" is not always a problem. If you use a SendMessage every once in a blue moon to notify scripts of a certain collision for instance, it doesn't matter that SendMessage is more expensive than direct calls. However, if you program your game to have large numbers of SendMessage per frame, you are bound to run into problems on the iPhone.

    Optimization is not about avoiding expensive code. It's about avoiding expensive code where it matters.


  6. Location
    Chicago
    Posts
    859
    ^Exactly.

    No real difference than characters; sure skin deformation is a more expensive, so you simply reduce mesh complexity, bone count and weight influences. That and fewer characters on screen at any one time.

    Expensive sure but not to be avoided as Tom stated.
    Steve Bodnar - Animation Director
    FlipFrame Animation/Games

    Recent Project - Bioshock Infinite
    Current Project - 'Unreleased'
    -------------------------------------------------
    Unity3D Pro / iOS Pro


  7. Location
    UK
    Posts
    232
    Thanks Guys

    I do understand all this. My coding experience goes back to the C64 and TRS-80 so I understand about optimizing my code and the impact of small delays when executed multiple times.

    What I don't understand and would like to learn is how much slower is it. All i've seen so far is statements that it's much slower. Is it 10ms rather than 5ms on an iPhone 3G? Does it use reflection? If it does is it on every call.

    In order for us to make intelligent decisions around flexibility over performance we need to understand the specifics. Would really appreciate a comment from the Unity Dev's.

    Thanks
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  8. Location
    Chicago
    Posts
    859
    Actually yea I don't believe we meant to state the obvious...

    ...so in all fairness I too would be curious what the difference is considering there are alternatives, albeit less 'simple'.



    -Steve
    Steve Bodnar - Animation Director
    FlipFrame Animation/Games

    Recent Project - Bioshock Infinite
    Current Project - 'Unreleased'
    -------------------------------------------------
    Unity3D Pro / iOS Pro


  9. Posts
    6,314
    If I was at my home computer I would throw together a quick test. Anyone care to see how long it takes to do n SendMessages vs n direct function calls? A few simple configurations would get a definitive answer quickly rather than speculating or waiting for a Unity dev.


  10. Location
    Zürich, Switzerland
    Posts
    26,572
    Quote Originally Posted by steddyman
    Does it use reflection? If it does is it on every call.
    Yes and Yes


    If you have to care about performance, cache the target component(s) so you can call them directly


  11. Location
    UK
    Posts
    232
    Thanks Dreamora

    At least that is a confirmation of how it works. There is no tidy way to cache these things though.

    I want a broadcast / subscriber model and it is not possible to do that without using SendMessage unless you resort to hard coding messages and compiling them into other scripts.
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  12. Location
    Phoenix, AZ
    Posts
    1,251
    Actually, I don't think it uses reflection each call. They're doing internal caching via hashtables or something...
    Matthew Wegner
    Current Project: Aztez
    Elsewhere:
    Founder, Flashbang Studios
    Partner, Indie Fund
    Editor, Fun-Motion
    Co-Chair, IGF


  13. Location
    UK
    Posts
    232
    Thanks for that.

    Again, would appreciate a post from a Unity internal dev team member on this one. I don't think anyone else could answer it for sure.

    If it does use Reflection, then shouldn't that mean the Asset Stripping feature which is a major benefit of the iPhone Advanced version cannot be used? It states clearly in the 1.51 manual that Asset Stripping it not safe even at the base level if Reflection is used. It makes no mention of SendMessage.
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  14. Location
    San Francisco, CA
    Posts
    901
    You know, if you just made a test script that sent a bunch of messages and timed it, it would take less time than you've spent on this thread. In fact, I got so annoyed that I went and wrote your test for you. The results:

    Editor:

    Time for SendMessage 1000 times: 0.00137501955032349
    Time for direct functon call 1000 times: 0.000117003917694092

    iPhone, no stripping, "Slow and Safe" call optimization:

    Time for SendMessage 1000 times: 0.0327930450439453
    Time for direct functon call 1000 times: 0.00520801544189453

    iPhone, micro mscorlib, "Fast but no exceptions":

    Time for SendMessage 1000 times: 0.0356040000915527
    Time for direct functon call 1000 times: 0.00104284286499023


    There's your answers: (a) Direct function calls are an order of magnitude faster. (b) SendMessage doesn't use reflection. (b) Call optimizations only work on function calls (which is sort of obvious now that I'm typing it out).

    On the iPhone a thousand SendMessage() calls performed in a loop will take 1/30 of a second (so one SendMessage takes 0.0000033333 second), while a thousand function calls take 1/200 of a second.

    So -- like others already told you -- native function calls are faster, not so much faster that it really matters unless you use them near-constantly. So use the NotificationCenter script already.


  15. Location
    UK
    Posts
    232
    Hi bliprob

    Sorry if I annoyed you. I was simply asking for details from Unity devs who moderate these forums for support reasons how their code actually worked. Performance was my main interest, but we still don't know how it is implemented under the seams. I didn't think asking for clarity would have annoyed anyone.

    I didn't attempt to time this myself because I didn't understand what the impact of SendMessage would be on the timing. Many people have posted on this forum that a SendMessage would be received on the next Update cycle rather than the current, which makes timing it pointless. In fact if your frame rate is 30 frames per second no matter how many calls you push at the call it should complete them in 1/30th of a second (so long as its not a million). Even if its one. Also, by nature SendMessage must be asynchronous whereas a direct call will wait for a return.

    Thanks for going the extra mile to implement the code and time this. Given your results for SendMessage was 1/30th of a second suggests this was because of the fact it is sending Async calls into the next Frame update. If you send 1200 you will probably find it takes the same length of time.
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol

  16. Volunteer Moderator
    Posts
    23,709
    I haven't seen anyone post that SendMessage would be received on the next Update, and if they did, that's quite wrong, and doesn't even make any sense.

    When running benchmarks, I use a substantially large number of iterations and get the average of several runs, since I've found that execution times vary somewhat.

    So, on my (rather old) machine, a loop of 5000000 SendMessage calls, using an empty function, takes 9.872 seconds. A loop of 5000000 direct calls (using a cached GetComponent) takes .024 seconds. Therefore, direct calling seems to be about 400 times faster, although considering that the loop itself takes up some time, it's probably more than that.

    That is, of course, a highly artificial benchmark. In real-world situations, it still makes sense to use SendMessage if that suits your design, and occasional SendMessage calls won't cause any noticeable performance issues. But in a situation where a large numbers of calls is needed, then yes, direct calling would be much faster, assuming you're using a cached GetComponent and not using it repeatedly (which is probably at least as slow as SendMessage).

    --Eric


  17. Location
    UK
    Posts
    232
    Thanks Eric

    Wow, that sure is a big difference. With a performance difference like that it will definitely be worth the extra overhead of not using SendMessage for my message passing system (it uses lots of messages).

    I did a lot of searching and research on these forums before posting this. I found quite a few references to SendMessage being Async. It kind of makes senses given it isn't necessarily a single function call since it will call the named functioned on ALL MonoBehaviour scripts attached to a GO.

    I did a quick search, and here were just a couple of threads that mentioned that SendMessage is received by the GO on the next frame:

    http://forum.unity3d.com/viewtopic.p...ht=sendmessage
    http://forum.unity3d.com/viewtopic.p...ht=sendmessage

    Thanks
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol

  18. Volunteer Moderator
    Posts
    23,709
    Quote Originally Posted by steddyman
    I did a quick search, and here were just a couple of threads that mentioned that SendMessage is received by the GO on the next frame:
    Mistaken, I'm afraid; not sure where that idea came from. It's not like SendMessage is physically sending a message that actually travels to other components and takes time to arrive. All it does is go through the attached components, finds matches of the desired function, and executes them. This is very easy to verify:

    Code:  
    1. function Start () {
    2.     SendMessage("Test");
    3.     print ("2");
    4.     yield;
    5.     print ("3");
    6. }
    7.  
    8. // The function below can be a separate script or not; doesn't make any difference
    9. function Test () {
    10.     print ("1");
    11. }

    If there was any sort of "delay to next frame", it would print 2, 1, 3, (or perhaps 2, 3, 1) but it doesn't; it prints 1, 2, 3. It would make some game logic very difficult and prone to breakage if there was any kind of async operation here. Hope this clears things up.

    --Eric


  19. Location
    UK
    Posts
    232
    It does and I appreciate you taking the time to explain that.

    I'm glad it works that way. It was hurting my head thinking about using it for sending collision messages. Now its is just the same as a function call.

    Thanks again
    Gigabyte Solutions Ltd
    Blog: www.gigabytesol.com
    Twitter Web: http://twitter.com/gigabytesol
    Twitter ID: @gigabytesol


  20. Location
    San Francisco, CA
    Posts
    901
    A factor of 400 times is definitely not what I'm seeing. I re-ddi the tests (Unity iPhone 1.5.1) with 500,000 iterations, averaged over ten runs:

    Desktop SendMessage: .0565 average
    Desktop direct call: 0.0635 average

    iPhone SendMessage: 16.9 average
    iPhone direct calls: 0.529 average

    In my testing it's 9 times faster on the desktop, and 32 times faster on the iPhone. (It's possible the results are very different with Unity 2.6, but I'm using Unity iPhone almost exclusively, so this is all I tested.)

    After testing this yesterday I added the NotificationCenter to my project. By decoupling it simplifies my code. If I need to optimize, I can.

Page 1 of 2 12 LastLast

Posting Permissions

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