Game Programming 13 - Debugging & Performance Optimization

Post on 13-Jan-2017

167 views 0 download

Transcript of Game Programming 13 - Debugging & Performance Optimization

Game ProgrammingDebugging & Performance Optimization

Nick Prühs

Objectives

• To get an overview of techniques for preventing bugs beforehand

• To learn how to track down and properly remove bugs from your code

• To understand possible performance bottlenecks

2 / 49

Why you should alwaysstart debugging immediately• Code entropy says your code will get worse, all the

time, unless you actively invest in preventing that

• Broken windows theory says the worse your code is, the worse it will become

• Tracking down bugs is harder in a larger code base

• Tracking down bugs is harder in a buggy code base

3 / 12

Code Quality Tools

4 / 12

Code Quality Tools

5 / 12

Code Quality Tools

6 / 12

/// <summary>

/// Attaches the passed component to the entity with the specified id.

/// Note that this manager does not check whether the specified id is valid.

/// </summary>

/// <exception cref="ArgumentNullException">

/// Passed component is null.

/// </exception>

/// <exception cref="InvalidOperationException">

/// There is already a component of the same type attached.

/// </exception>

public void AddComponent(int entityId, IEntityComponent component)

{

if (component == null)

{

throw new ArgumentNullException("component");

}

if (this.components.ContainsKey(entityId))

{

throw new InvalidOperationException(

"There is already a component of type " + component.GetType() + " attached to entity with id "

+ entityId + ".");

}

this.components.Add(entityId, component);

this.OnComponentAdded(entityId, component);

}

You need a repro. Period.

How can you be sure you’ve fixed it?

7 / 12

Stack Traces

Object reference not set to an instance of an object

at LifeApplication.Initializer.CreateManagers () [0x00488] in Initializer.cs:481

at LifeApplication.Initializer.OnLoad () [0x00016] in Initializer.cs:235

8 / 12

What’s null here?

// Initialize progress manager.

var progressConfig = newProgressConfig(this.unityLoader.Version.Code);

if (this.config.Progress.Encrypt)

{

progressConfig.SetEncryption(

this.config.Progress.Encryption.EncryptKey,

this.config.Progress.Encryption.EncryptIv);

}

9 / 12

What’s null here?

// Initialize progress manager.

var progressConfig = newProgressConfig(this.unityLoader.Version.Code);

if (this.config.Progress.Encrypt)

{

progressConfig.SetEncryption(

this.config.Progress.Encryption.EncryptKey,

this.config.Progress.Encryption.EncryptIv);

}

10 / 12

What’s null here?

// Initialize progress manager.

var progressConfig = newProgressConfig(this.unityLoader.Version.Code);

if (this.config.Progress.Encrypt)

{

progressConfig.SetEncryption(

this.config.Progress.Encryption.EncryptKey,

this.config.Progress.Encryption.EncryptIv);

}

11 / 12

What’s null here?

// Initialize progress manager.

var progressConfig = newProgressConfig(this.unityLoader.Version.Code);

if (this.config.Progress.Encrypt)

{

progressConfig.SetEncryption(

this.config.Progress.Encryption.EncryptKey,

this.config.Progress.Encryption.EncryptIv);

}

12 / 12

What’s null here?

// Initialize progress manager.

var progressConfig = newProgressConfig(this.unityLoader.Version.Code);

if (this.config.Progress.Encrypt)

{

progressConfig.SetEncryption(

this.config.Progress.Encryption.EncryptKey,

this.config.Progress.Encryption.EncryptIv);

}

13 / 12

What’s null here?

// Initialize progress manager.

var progressConfig = newProgressConfig(this.unityLoader.Version.Code);

if (this.config.Progress.Encrypt)

{

progressConfig.SetEncryption(

this.config.Progress.Encryption.EncryptKey,

this.config.Progress.Encryption.EncryptIv);

}

14 / 12

Divide-and-conquer

15 / 12

Divide-and-conquer

16 / 12

Divide-and-conquer

17 / 12

Divide-and-conquer

18 / 12

Divide-and-conquer

19 / 12

Divide-and-conquer

20 / 12

Conditional Breakpoints

21 / 12

Logging

22 / 12

On-Screen

23 / 12

Crash Dump Analaysis

24 / 43

C:\Program Files\Procdump>procdump.exe -ma -i D:\Temp\Dumps

ProcDump v7.0 - Writes process dump files

Copyright (C) 2009-2014 Mark Russinovich

Sysinternals - www.sysinternals.com

With contributions from Andrew Richards

Set to:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

(REG_SZ) Auto = 1

(REG_SZ) Debugger = "C:\Program Files\Procdump\procdump.exe" -accepteula -ma

-j "D:\Temp\Dumps" %ld %ld %p

Set to:

HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug

(REG_SZ) Auto = 1

(REG_SZ) Debugger = "C:\Program Files\Procdump\procdump.exe" -accepteula -ma

-j "D:\Temp\Dumps" %ld %ld %p

ProcDump is now set as the Just-in-time (AeDebug) debugger.

Crash Dump Analaysis

25 / 43

C:\Program Files\Procdump>procdump.exe -u

ProcDump v7.0 - Writes process dump files

Copyright (C) 2009-2014 Mark Russinovich

Sysinternals - www.sysinternals.com

With contributions from Andrew Richards

Reset to:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

(REG_SZ) Auto = <deleted>

(REG_SZ) Debugger = "C:\WINDOWS\system32\vsjitdebugger.exe" -p %ld -e %ld

Reset to:

HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug

(REG_SZ) Auto = <deleted>

(REG_SZ) Debugger = "C:\WINDOWS\system32\vsjitdebugger.exe" -p %ld -e %ld

ProcDump is no longer the Just-in-time (AeDebug) debugger.

Crash Dump Analaysis

26 / 43

Deferencing a nullptr that will cause a crash

Crash Dump Analaysis

27 / 43

Minidump File Summary in Visual Studio

Crash Dump Analaysis

28 / 43

Debugging a Minidump in Visual Studio

Pair Programming

29 / 12Source: University of Utah, UIT

And if nothings helps …

30 / 12

And if nothings helps …

31 / 12

TRY AGAIN TOMORROW!

Some are really nasty …

• Remote systems

• Race conditions

• Mobile development, embedded systems, drivers

• “Release Mode only” bugs

32 / 12

Quoting My Tutor

“If the bug is not where you expect it to be,

you better start looking for it where you’re not expecting it to be.”

- Hagen Peters

33 / 12

Why you should neverstart optimizing immediately• Your code base will change over time, a lot, most

likely removing some of the code you’ve spent time on optimizing

• Optimized code tends to be hard to read• … and thus, hard to debug.

34 / 12

Performance Optimization

1. Profile first!

35 / 12

Performance Optimization

1. Profile first!

2. Profile again!

36 / 12

Performance Optimization

1. Profile first!

2. Profile again!

3. Identify the bottlenecks: CPU vs. GPU vs. Memory

37 / 12

Fighting CPU Bottlenecks

Pooling

Trades memory for CPU performance.

Re-uses objects to prevent costly construction and destruction.

Requires proper (cheap) reset of pooled objects.

38 / 12

Fighting CPU Bottlenecks

Caching

Trades memory for CPU performance.

Stores computed values for later use.

Requires proper cache invalidation whenever the input changes.

39 / 12

Fighting CPU Bottlenecks

Bucketing

Trades accuracy for CPU performance.

Distributes computations across multiple frames by dividing operation into multiple input sets.

Can only be applied if player doesn’t notice difference immediately (e.g. updating AI just twice per second).

40 / 12

Memory Bottleneck

41 / 12

Memory Bottleneck

42 / 12

Memory Bottleneck

43 / 12

GPU Bottleneck

44 / 12

Frame Debugger

45 / 12

Frame Debugger

46 / 12

Frame Debugger

47 / 12

Frame Debugger

48 / 12

Frame Debugger

49 / 12

Gotcha!

Always turn off logging before profiling!

Otherwise, disk I/O will lead to false results.

50 / 28

Hint

If no native profiling tools are available (or applicable), you can always fall back to utility classes

such as System.Diagnostics.Stopwatch.

51 / 28

References

• McShaffry. Debugging Your Game … or “That’s not supposed to happen!”. Austin Game Conference, 2003.

52 / 28

Thank you!

http://www.npruehs.de

https://github.com/npruehs

@npruehs

dev@npruehs.de