Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Game Programming 13 - Debugging & Performance Optimization

416 views

Published on

Chapter 13 of the lecture Game Programming taught at HAW Hamburg.

Introduction to diagnostics tools, debugging and performance optimization.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Game Programming 13 - Debugging & Performance Optimization

  1. 1. Game Programming Debugging & Performance Optimization Nick Prühs
  2. 2. 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 / 55
  3. 3. Why you should always start 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 / 55
  4. 4. Code Quality Tools 4 / 55
  5. 5. Code Quality Tools 5 / 55
  6. 6. Code Quality Tools 6 / 55 /// <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); }
  7. 7. You need a repro. Period. How can you be sure you’ve fixed it? 7 / 55
  8. 8. 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 / 55
  9. 9. What’s null here? // Initialize progress manager. var progressConfig = new ProgressConfig(this.unityLoader.Version.Code); if (this.config.Progress.Encrypt) { progressConfig.SetEncryption( this.config.Progress.Encryption.EncryptKey, this.config.Progress.Encryption.EncryptIv); } 9 / 55
  10. 10. What’s null here? // Initialize progress manager. var progressConfig = new ProgressConfig(this.unityLoader.Version.Code); if (this.config.Progress.Encrypt) { progressConfig.SetEncryption( this.config.Progress.Encryption.EncryptKey, this.config.Progress.Encryption.EncryptIv); } 10 / 55
  11. 11. What’s null here? // Initialize progress manager. var progressConfig = new ProgressConfig(this.unityLoader.Version.Code); if (this.config.Progress.Encrypt) { progressConfig.SetEncryption( this.config.Progress.Encryption.EncryptKey, this.config.Progress.Encryption.EncryptIv); } 11 / 55
  12. 12. What’s null here? // Initialize progress manager. var progressConfig = new ProgressConfig(this.unityLoader.Version.Code); if (this.config.Progress.Encrypt) { progressConfig.SetEncryption( this.config.Progress.Encryption.EncryptKey, this.config.Progress.Encryption.EncryptIv); } 12 / 55
  13. 13. What’s null here? // Initialize progress manager. var progressConfig = new ProgressConfig(this.unityLoader.Version.Code); if (this.config.Progress.Encrypt) { progressConfig.SetEncryption( this.config.Progress.Encryption.EncryptKey, this.config.Progress.Encryption.EncryptIv); } 13 / 55
  14. 14. What’s null here? // Initialize progress manager. var progressConfig = new ProgressConfig(this.unityLoader.Version.Code); if (this.config.Progress.Encrypt) { progressConfig.SetEncryption( this.config.Progress.Encryption.EncryptKey, this.config.Progress.Encryption.EncryptIv); } 14 / 55
  15. 15. Divide-and-conquer 15 / 55
  16. 16. Divide-and-conquer 16 / 55
  17. 17. Divide-and-conquer 17 / 55
  18. 18. Divide-and-conquer 18 / 55
  19. 19. Divide-and-conquer 19 / 55
  20. 20. Divide-and-conquer 20 / 55
  21. 21. Conditional Breakpoints 21 / 55
  22. 22. Logging 22 / 55
  23. 23. On-Screen 23 / 55
  24. 24. Crash Dump Analaysis 24 / 55 C:Program FilesProcdump>procdump.exe -ma -i D:TempDumps ProcDump v7.0 - Writes process dump files Copyright (C) 2009-2014 Mark Russinovich Sysinternals - www.sysinternals.com With contributions from Andrew Richards Set to: HKLMSOFTWAREMicrosoftWindows NTCurrentVersionAeDebug (REG_SZ) Auto = 1 (REG_SZ) Debugger = "C:Program FilesProcdumpprocdump.exe" -accepteula -ma -j "D:TempDumps" %ld %ld %p Set to: HKLMSOFTWAREWow6432NodeMicrosoftWindows NTCurrentVersionAeDebug (REG_SZ) Auto = 1 (REG_SZ) Debugger = "C:Program FilesProcdumpprocdump.exe" -accepteula -ma -j "D:TempDumps" %ld %ld %p ProcDump is now set as the Just-in-time (AeDebug) debugger.
  25. 25. Crash Dump Analaysis 25 / 55 C:Program FilesProcdump>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: HKLMSOFTWAREMicrosoftWindows NTCurrentVersionAeDebug (REG_SZ) Auto = <deleted> (REG_SZ) Debugger = "C:WINDOWSsystem32vsjitdebugger.exe" -p %ld -e %ld Reset to: HKLMSOFTWAREWow6432NodeMicrosoftWindows NTCurrentVersionAeDebug (REG_SZ) Auto = <deleted> (REG_SZ) Debugger = "C:WINDOWSsystem32vsjitdebugger.exe" -p %ld -e %ld ProcDump is no longer the Just-in-time (AeDebug) debugger.
  26. 26. Crash Dump Analaysis 26 / 55 Deferencing a nullptr that will cause a crash
  27. 27. Crash Dump Analaysis 27 / 55 Minidump File Summary in Visual Studio
  28. 28. Crash Dump Analaysis 28 / 55 Debugging a Minidump in Visual Studio
  29. 29. Pair Programming 29 / 55 Source: University of Utah, UIT
  30. 30. And if nothings helps … 30 / 55
  31. 31. And if nothings helps … 31 / 55 TRY AGAIN TOMORROW!
  32. 32. Some are really nasty … • Remote systems • Race conditions • Mobile development, embedded systems, drivers • “Release Mode only” bugs 32 / 55
  33. 33. 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 / 55
  34. 34. Why you should never start 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 / 55
  35. 35. Performance Optimization 1. Profile first! 35 / 55
  36. 36. Performance Optimization 1. Profile first! 2. Profile again! 36 / 55
  37. 37. Performance Optimization 1. Profile first! 2. Profile again! 3. Identify the bottlenecks: GPU vs. CPU vs. Memory 37 / 55
  38. 38. 38 / 55
  39. 39. GPU Bottleneck 39 / 55
  40. 40. Frame Debugger 40 / 55
  41. 41. Frame Debugger 41 / 55
  42. 42. Frame Debugger 42 / 55
  43. 43. Frame Debugger 43 / 55
  44. 44. Frame Debugger 44 / 5
  45. 45. 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. 45 / 55
  46. 46. Fighting CPU Bottlenecks Caching Trades memory for CPU performance. Stores computed values for later use. Requires proper cache invalidation whenever the input changes. 46 / 55
  47. 47. 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). 47 / 55
  48. 48. Memory Bottleneck 48 / 55
  49. 49. Memory Bottleneck 49 / 55
  50. 50. Memory Bottleneck 50 / 55
  51. 51. Gotcha! Always turn off logging before profiling! Otherwise, disk I/O will lead to false results. 51 / 55
  52. 52. Hint If no native profiling tools are available (or applicable), you can always fall back to utility classes such as System.Diagnostics.Stopwatch. 52 / 55
  53. 53. Memory Leaks • allocated memory that is never released ▪ in most cases, the reference or pointer is not even available any more ▪ if occurring on a regular basis (e.g. every time a level is loaded), will eventually fill up all available memory and crash the game • in Ansi C: “no malloc without free” • in C++: “no new without delete” ▪ in modern C++, usually achieved by the means of smart pointers
  54. 54. Gotcha! Managed runtime environments can leak memory, too! 54 / 55
  55. 55. Memory Leaks • make sure to always remove all registered event handlers in languages like C# • more complicated runtime environments can represent unique challenges ▪ e.g. Mono heap in Unity • it might be a good idea to return to an “empty scene” once in a while and verify all memory has been properly cleaned up
  56. 56. Memory Leak in Unity
  57. 57. Memory Leak in Unity
  58. 58. References • McShaffry. Debugging Your Game … or “That’s not supposed to happen!”. Austin Game Conference, 2003. 58 / 55
  59. 59. Thank you! http://www.npruehs.de https://github.com/npruehs @npruehs nick.pruehs@daedalic.com
  60. 60. 5 Minute Review Session • Why should you always start debugging immediately? • Why should you never start optimizing immediately? • Name a few tools and approaches for tracking down broken code! • How do you know whether you’ve got an GPU, CPU or memory bottleneck? • Name a few techniques for fighting CPU bottlenecks!

×