Performance observations

104 views
Skip to first unread message

Josef Bodnár

unread,
Jun 5, 2017, 7:24:37 AM6/5/17
to StrangeIoC
I have started looking at performance with StrangeIoC, because I am invoking quite a lot of simple commands in the game loop.
My first concern is per-frame overhead (esp. gc alloc) necessary for the strangeIoC infrastructure.

Disclaimer:
I know I am overusing strangeIoC in ways it was not primarilly ment to be used.
I am not criticizing how strangeIoC works, I am just trying to find ways to make it run with less overhead.
Findings below apply to stuff that is called ~hundred times per second, if you call something once per second, you would not probably notice it.

I have found following:
- a lot of strangeIoC code uses foreach, which is known to allocate memory, converting those to for loops will fix it (simple editor command)
- at some places, dictionary access can be simplified by using TryGetValue, this also reduces memory alloc a lot (Binder.GetBinding)
- command pooling did not fix much of the gc allocation, but helped (don't have exact numbers, sorry, no time for proper measurements)
- passing data to commands via signal seems to be more costly than injection from the context (see SignalCommandBinder.createCommandForSignal), so pass only those things, that are not obtainable any simpler way
- Injector.armorAgainstInfiniteLoops seems to consume memory a lot as well
- the main issue with GC allocation for me now is the use of reflection and object allocation

I have tried moving my frequent commands from setter injection to construction injection, which seems to use less memory (skips reflection for every property), but (stupid me), now you can't use pooling of course. So this is no-go for me.

As an alternative, I tried using a single method with [PostConstruct] and then inside calling injectionBinder.GetInstance<MyType>(); for each injected property. However, this also uses reflection to find the postconstruct method and costs some allocation.
One way to get rid of the reflection would be to introduce a special interface e.g. "BindingInitializer" interface with a postConstruct() method. This could be checked prior to the reflection.

The most extreme solution would be to leave all the setup, injections, unprocessed signal data, etc. to the Command directly.

To sum up:
- there is room for optimization in code
  - I would gladly send you the changes I made in the, however, I am not familiar with the github contribution process :-(
- there should be a single way to setup a command for performance (even if not as flexible and code-pretty as current solutions)
- I would suggest to also review the injectionBinder.GetInstance<>() method and make it as optimized as possible

Thanks,
Josef

Josef Bodnár

unread,
Jun 6, 2017, 6:27:44 AM6/6/17
to StrangeIoC
Just to get you the picture what happens...

I have a "unit" test where I start a dedicated server (the backend part with strangeIoC) and let it run with a simulated game for 30 seconds. The tickrate is 200 times a second.
Every tick, multiple commands are invoked, all having multiple properties injected via setters.

The number of calls to some strangeIoC functions goes to millions. Here is a profiler screenshot focused on the strangeioc assembly.
It shows the functions with most calls.



This is just to illustrate how quickly can the overhead arise if you start overusing the StrangeIoC and the importance of having things optimized.


Dne pondělí 5. června 2017 13:24:37 UTC+2 Josef Bodnár napsal(a):
Auto Generated Inline Image 1

wco...@gmail.com

unread,
Jun 6, 2017, 9:54:52 AM6/6/17
to Josef Bodnár, StrangeIoC
Haven't had time to look at this in depth but I read the posts on my phone.

Excellent work. I do worry you've mostly just entered into the area we warn users not to go with strange. Overuse in game loops is advised against by us just as with any framework.

I'll take a closer peek tonight or tomorrow and see what can be done to improve though. Armor against is definitely a culprit. And we could help by adding a Cached() fluent method option for bindings that are accessed very often. 

Thanks again. About to head outdoors with family so can't go in depth!

Sent from my iPhone

On Jun 6, 2017, at 3:27 AM, Josef Bodnár <josef....@ticklersoft.com> wrote:

Just to get you the picture what happens...

I have a "unit" test where I start a dedicated server (the backend part with strangeIoC) and let it run with a simulated game for 30 seconds. The tickrate is 200 times a second.
Every tick, multiple commands are invoked, all having multiple properties injected via setters.

The number of calls to some strangeIoC functions goes to millions. Here is a profiler screenshot focused on the strangeioc assembly.
It shows the functions with most calls.

<Auto Generated Inline Image 1>

--
You received this message because you are subscribed to the Google Groups "StrangeIoC" group.
To unsubscribe from this group and stop receiving emails from it, send an email to strangeioc+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
<Auto Generated Inline Image 1>

wcorwin

unread,
Jun 9, 2017, 12:19:38 AM6/9/17
to StrangeIoC, josef....@ticklersoft.com
Hey Josef, let's talk about some optimizations. I'd like to hear more about your findings. A lot of the reflection should be cached. The fact that you're doing 200 ticks a second and racking up millions of method calls doesn't really bother me, are you seeing any leaks or methods which are eating up cycles? Foreach shouldn't be generating extra garbage, which version of unity are you running? Do you have profiling to show where it is? Same for GetInstance.

I'm always happy to improve performance. ArmorAgainst we've seen evidence against in the past and I didn't have a great answer then. Let's make sure there are real concerns and get some profiling in place and make sure we're improving things in a measurable way.

Shoot me an email with a couple of times you're available to talk/skype. Thanks!

Hữu Lộc

unread,
Jan 28, 2018, 7:28:13 AM1/28/18
to StrangeIoC
Hi @wcorwin,

Do we have any conclusion on this issue?
Is there anything that we can do to boost the performance of StrangeIoC?

wcorwin

unread,
Feb 6, 2018, 7:16:10 PM2/6/18
to StrangeIoC
I'm not sure "boost the performance" is a meaningful term. Is there something in particular you're seeing in the profiler which is causing issues? Strange should be very performant.
Reply all
Reply to author
Forward
0 new messages