IL2CPP: Debugging and Profiling

50
IL2CPP: Profiling and Debugging Jonathan Chambers and Josh Peterson

Transcript of IL2CPP: Debugging and Profiling

Page 1: IL2CPP: Debugging and Profiling

IL2CPP: Profiling and Debugging

Jonathan Chambers andJosh Peterson

Page 2: IL2CPP: Debugging and Profiling

Agenda

Page 3: IL2CPP: Debugging and Profiling

The Abridged Version

IL2CPP

Page 4: IL2CPP: Debugging and Profiling

Where is IL2CPP?

Page 5: IL2CPP: Debugging and Profiling

Creating IL2CPP

Page 6: IL2CPP: Debugging and Profiling

How do we make IL2CPP?

Page 7: IL2CPP: Debugging and Profiling

Fundamental principle: Test first• Unit tests - C++ and C# (~500)• Integration tests (~2000)• Platform integration tests (~1000)

Code conversion (il2cpp.exe) - C#Runtime (libil2cpp) - C++

How do we make IL2CPP?

Page 8: IL2CPP: Debugging and Profiling

Tools we use

Page 9: IL2CPP: Debugging and Profiling

• We debug with an IL2CPP standalone player

• We check build time and size against real projects

Internal tools

Page 10: IL2CPP: Debugging and Profiling

Internal organization of libil2cpp code

Internal Calls

Generated Code

PALVM

iOS

Windows

Other Platform

Page 11: IL2CPP: Debugging and Profiling

Our goal: move fast

Photo credit: Alvesgaspar (CC BY-SA 3.0)

Page 12: IL2CPP: Debugging and Profiling

Debugging script code with IL2CPP

Page 13: IL2CPP: Debugging and Profiling

Best option: Debug code in the editor

Acceptable option: Debug on device with Mono backend

Debugging script code with IL2CPP

Most fun option: Debug the generated C++ code!

Page 14: IL2CPP: Debugging and Profiling

When to debug generated C++ code

An exception occurs only on the device Marshaling

Interaction with native code

Page 15: IL2CPP: Debugging and Profiling

Deep dive: Debugging a managed exception in generated C++ code

Page 16: IL2CPP: Debugging and Profiling

• The converted code is the IL code, not C# code• Filter underscore characters from names• Sanity check often• Understand managed type layouts in native code

Principles for debugging generated code

Page 17: IL2CPP: Debugging and Profiling

• Debugging generated C++ code is probably not a technique to use often.

• Generated code will change in newer versions.• Generated C++ code can give Xcode problems.

Caveats

But for certain situations, this is a great skill to use!

Page 18: IL2CPP: Debugging and Profiling

Check out our IL2CPP Internals blog series!

Debugging tips for generated code - http://blogs.unity3d.com/2015/05/20/il2cpp-internals-debugging-tips-for-generated-code/

More information

Page 19: IL2CPP: Debugging and Profiling

Performance and Profiling

Page 20: IL2CPP: Debugging and Profiling
Page 21: IL2CPP: Debugging and Profiling

We make things fast for you!

The Good News

Page 22: IL2CPP: Debugging and Profiling

Make it small and make it fast!

Speed *and* Size

Page 23: IL2CPP: Debugging and Profiling

Make your code fast in general

.Net Profiler

Page 24: IL2CPP: Debugging and Profiling

Make your code fast in Unity

Unity Profiler

Page 25: IL2CPP: Debugging and Profiling

Make your code fast on device

Native Profiler

Page 26: IL2CPP: Debugging and Profiling

var md5 = MD5.Create(); var values = new byte[1024*1024]; var random = new Random(100); random.NextBytes(values); TimeAction (() => md5.ComputeHash(values));

Example

Page 27: IL2CPP: Debugging and Profiling

MD5 Hash

0ms

25ms

50ms

75ms

100ms

iPod 4G

Unity Mono IL2CPP

Page 28: IL2CPP: Debugging and Profiling

MD5 Hash

0ms

25ms

50ms

75ms

100ms

iPod 4G iPhone 6

Unity Mono IL2CPP

Page 29: IL2CPP: Debugging and Profiling

struct Vector2 { public float X; public float Y; public Vector2(float x, float y) { X = x; Y = x; } public float Magnitude() { return (float)Math.Sqrt(X*X + Y*Y); } }

Example 2

Page 30: IL2CPP: Debugging and Profiling

const int kNumItems = 1000000; var vals = new Vector2[kNumItems]; for (var i = 0; i < values.Length; i++) values[i] = new Vector2(i, values.Length - i); TimeAction (() => Array.Sort (vals, new Vector2Comparer ()));

Example 2 - cont’d

Page 31: IL2CPP: Debugging and Profiling

class Vector2Comparer : IComparer { public int Compare(object x, object y) { var v1 = (Vector2) x; var v2 = (Vector2) y; var mag1 = v1.Magnitude(); var mag2 = v2.Magnitude(); if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; } }

IComparer

Page 32: IL2CPP: Debugging and Profiling

Instruments

Page 33: IL2CPP: Debugging and Profiling

class Vector2Comparer_v2 : IComparer<Vector2>{ public int Compare(Vector2 v1, Vector2 v2) { var mag1 = v1.Magnitude(); var mag2 = v2.Magnitude(); if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; } }

IComparer<T>

Page 34: IL2CPP: Debugging and Profiling
Page 35: IL2CPP: Debugging and Profiling

Interface - iPod 4G

0s

10s

20s

30s

40s

IComparer IComparer<T>

IL2CPP

Page 36: IL2CPP: Debugging and Profiling

static int CompareVector2 (Vector2 v1, Vector2 v2){ var mag1 = v1.Magnitude(); var mag2 = v2.Magnitude(); if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; }

Delegate v1

Page 37: IL2CPP: Debugging and Profiling

static int CompareVector2_v2(Vector2 v1, Vector2 v2){ var mag1 = Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y); var mag2 = Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y); if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; }

Delegate v2

Page 38: IL2CPP: Debugging and Profiling

Delegate Optimization? - iPod 4G

0s

2s

4s

6s

8s

Method Call Inline

IL2CPP

Page 39: IL2CPP: Debugging and Profiling

static int CompareVector2_v2(Vector2 v1, Vector2 v2){ var mag1 = Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y); var mag2 = Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y); if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; } // Our function we inlined public float Magnitude() { return (float)Math.Sqrt(X*X + Y*Y); }

Delegate v2 - What’s going on?

Page 40: IL2CPP: Debugging and Profiling

static int CompareVector2_v2(Vector2 v1, Vector2 v2){ var mag1 = (float)Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y); var mag2 = (float)Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y); if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; }

Delegate v2 - Corrected

Page 41: IL2CPP: Debugging and Profiling

Delegate - iPod 4G

0s

2s

4s

6s

8s

Method Call Inline Inline Fixed

IL2CPP

Page 42: IL2CPP: Debugging and Profiling

static int CompareVector2_v3(Vector2 v1, Vector2 v2){ var mag1 = v1.X * v1.X + v1.Y * v1.Y; var mag2 = v2.X * v2.X + v2.Y * v2.Y; if (mag1 > mag2) return 1; if (mag1 < mag2) return -1; return 0; }

Delegate v3

Page 43: IL2CPP: Debugging and Profiling

Delegate - iPod 4G

0s

1.5s

3s

4.5s

6s

Method Call Inline No Sqrt

IL2CPP

Page 44: IL2CPP: Debugging and Profiling

Vector2 Sort by Magnitude - iPod 4G

0s

35s

70s

105s

140s

IComparable IComparable<T> Delegate 1 Delegate 2 Delegate 3

Unity Mono IL2CPP

Page 45: IL2CPP: Debugging and Profiling

Two More Things

Page 46: IL2CPP: Debugging and Profiling

Fast and Unsafe

Page 47: IL2CPP: Debugging and Profiling

public float Magnitude() { Debug.Log ("Let's slow things down!"); return (float)Math.Sqrt(X*X + Y*Y); }

One Time Initialization

Page 48: IL2CPP: Debugging and Profiling

public float Magnitude() { Debug.Log ("Let's slow things down!"); return (float)Math.Sqrt(X*X + Y*Y); }

// Generated C++ prologue static bool s_Il2CppMethodIntialized; if (!s_Il2CppMethodIntialized) { _stringLiteral0 = il2cpp_codegen_string_literal_from_index(0); s_Il2CppMethodIntialized = true; }

One Time Initialization

Page 49: IL2CPP: Debugging and Profiling

Thank you!

Page 50: IL2CPP: Debugging and Profiling

@jon_cham@petersonjm1

Questions?