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