Slideshare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.

Slideshare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.

【Unite 2017 Tokyo】パフォーマンス向上のためのスクリプトのベストプラクティス(note付き)

5.
The VM is an abstract stack machine.
It means we take operands that reside on an evaluation stack.
The instruction set consists of instructions that push operands on the abstract evaluation stack.
All operands that may be placed on this stack are drawn from a small set of primitive types.
Then the IL (our PEM, program executable module) is used by the JIT or is getting AOT compiled
5

6.
ldarg.1 loads an argument (passed as a parameter) onto the stack
Ldc.i4.0 Pushes a supplied value of type int32 onto the evaluation stack as an int32
Blt Transfers control to a target instruction if the first value is less than the second value
6

7.
As we can see, we take the variable INPUT and send it to L_0
In the instruction set there only branching and jumping to do if and loops
And you can find the IL2CPP cpp code in the directory at the bottom of the slide
Or load the IL2CPP project with Xcode.
7

16.
What is unmanaged code?
Unmanaged code is basically code written in C/C++ without the safety net that managed code provides.
While managed code is generally great, there are times when you either need to interface directly with
other modules / hardware for a specific feature which .Net doesn’t provide. For example, if you want to
directly interface with a printer port or peripheral or interface with a package that’s written in C/C++
Note: I’m using ‘native’ and unmanaged code interchangably.
16

17.
Accessing DLL’s from managed code may seem straight-forward and while it generally is, there are
some pitfalls. For instance, figuring out where to put the DLL or library. For both Windows and OSX you
17

19.
Depending on the platform you’re developing for, you may have to make sure that functions adhere to
the C ABI (Application Binary Interface). Depending on the platform and the compiler you’re using, you
may have to change intrinsics to ensure everything is working correctly.
Caveats primarily being exceptions, as discussed in the next slide.
21

20.
Depending on the platform you’re developing for, you may have to make sure that functions adhere to
the C ABI (Application Binary Interface). Depending on the platform and the compiler you’re using, you
may have to change intrinsics to ensure everything is working correctly.
22

21.
Marshalling is the process of converting parameters for managed code over into unmanaged code. While
it’s relatively straightforward for simple types, things get more interesting when data needs to be
converted or when memory needs to be allocated.
For examples, strings fit this description in that there could be a number of different formats, ranging
from ASCII to UTF8 to UFT16. Aside from the unicode conversion, there is also the issues of copying the
data over.
If you want to ensure memory sticks around when calling unmanaged code, use the c# ‘fixed’ statement.
Otherwise, all bets are off
Generally, memory is copied around to ensure nothing gets corrupted. For obvious reasons, this process
can be slow.
23

22.
Objects are marshalled differently based on their type. For example, a string version may have multiple
functions that LOOK the same but actually have different entrypoints to handle different types of text.
The reason for this is to be able to handle different variations that all share the same function but handle
parameters differently.
24

23.
Objects are marshalled differently based on their type. For example, a string version may have multiple
functions that LOOK the same but actually have different entrypoints to handle different types of text.
The reason for this is to be able to handle different variations that all share the same function but handle
parameters differently.
As a rule of thumb, in/out variables and / or structures should be copied back and forth to avoid causing
problems.
25

24.
One of the bigger pitfalls of mixing managed / unmanaged code is to make sure you keep track of who
owns what. Not doing so may result in strange / unidentifiable behavior or crashes that are going to be
hard to track.
When you’re using allocations in Unmanaged code, use the same memory pool as managed code. Don’t
mix and match.
If you want, you can create custom Marshall functions.
26

25.
Unless you have a valid reason to do native / unmanaged code, stick with managed code as it will make
your life easier.
27

32.
I’ve heard that foreach is allocating memory, is it true?
Let’s have a look….
34

33.
The compiler is smart enough to transform foreach usage on Arrays to a simple for loop. The decompiled
IL looks like the following C#
The truth is that The "hidden" allocations that occur when using foreach normally occurs due to boxing
(or constructing) the enumerator or the values themselves in the case of value types.
So, as we can see, there should be no overhead for either performance or memory allocations when
doing a foreach on an Array.
35

34.
Nevertheless, as you do the implementation of your Enumerator, be careful that you don’t do boxing on
your enumerator.
[internal : https://q.unity3d.com/questions/1465/when-does-using-foreach-in-c-cause-an-allocation.html#]
36

47.
First we check if the gameobject is null, that means a call to the op_Equalit that takes two
UnityEngine.Objects as parameters
Then, if it’s not null, we jump at the very end of the function to do
ldsfld class SingleGameFind SingletonGameFind::m_instance
ldsfld simply Push the value of a static field on the stack
What’s on the stack is what we return
48

51.
GetCachedPtr takes 0.34ms
Op_Inequality takes 0.35ms
Really? Nope, that is because what I look at is wrong
52

52.
In the editor, we use a different UnityEngine.dll … so NEVER EVER PROFILE in the editor.
53

53.
In the editor, we use a different UnityEngine.dll … so NEVER EVER PROFILE in the editor.
54

54.
The true result is that, without doing the Callvirt, it’s still about 6 times faster…
And I was wondering if using a property was changing anything, not only the IL told me no but the profiler
too.
No virtcall is ever inlined in C#
55

58.
MonoBehaviour vs class?
Check at the blog post from Valentin
https://blogs.unity3d.com/2015/12/23/1k-update-calls/
Sealed
micro opt of no virt call with the animal / cow example with IL2CPP only
Static
No diff
Unsafe
If you use struct and native, no diff
LINQ
Creates a lot of overhead, avoid
Generic
Can create a lot of overhead, check IL
59