Is SendMessage really that bad?

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

http://www.unifycommunity.com/wiki/index.php?title=NotificationCenter

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

1 Like

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?

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.php?t=40311&start=15#249309

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

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.

1 Like

^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.

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

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ā€™.

:smile:

-Steve

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.

Yes and Yes

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

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.

Actually, I donā€™t think it uses reflection each call. Theyā€™re doing internal caching via hashtables or somethingā€¦

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.

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.

6 Likes

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.

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

1 Like

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.php?t=27285&highlight=sendmessage
http://forum.unity3d.com/viewtopic.php?t=19954&highlight=sendmessage

Thanks

1 Like

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:

function Start () {
	SendMessage("Test");
	print ("2");
	yield;
	print ("3");
}

// The function below can be a separate script or not; doesn't make any difference
function Test () {
	print ("1");
}

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. :slight_smile:

ā€“Eric

1 Like

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

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.