Tanoda
LeapProfiling.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using System.Threading;
10using System.Collections.Generic;
11using UnityEngine;
12using UnityEngine.Profiling;
13
14namespace Leap.Unity {
15
19 public static class LeapProfiling {
20
21 //Maps a block name to the sampler for it
22 private static Dictionary<string, CustomSampler> _samplers = new Dictionary<string, CustomSampler>();
23
24 //Represents a queue of samplers that need to be created.
25 //Samplers can only be created on the main thread, so we need some way for the info given
26 //on alternate threads to be passed to the main thread.
27 private static Queue<string> _samplersToCreate = new Queue<string>();
28
29 //We keep track of the size of the queue in a member variable
30 private static int _samplersToCreateCount = 0;
31
32 public static void Update() {
33 //Read of _samplersToCreateCount is atomic
34 if (_samplersToCreateCount > 0) {
35 //Only if the count is nonzero do we do an expensive lock
36 lock (_samplersToCreate) {
37 //First duplicate the existing dictionary
38 var newDictionary = new Dictionary<string, CustomSampler>(_samplers);
39
40 //Then construct all of the new samplers and add them to the new dictionary
41 while (_samplersToCreate.Count > 0) {
42 string blockName = _samplersToCreate.Dequeue();
43
44 newDictionary[blockName] = CustomSampler.Create(blockName);
45 }
46
47 //Reset samplers to create to zero
48 _samplersToCreateCount = 0;
49
50 //Reference assignments are atomic in C#
51 //All new callbacks will now reference the updated dictionary
52 //Old dictionary will be collected by GC
53 _samplers = newDictionary;
54 }
55 }
56 }
57
58 public static void BeginProfilingForThread(BeginProfilingForThreadArgs eventData) {
59#if UNITY_2017_3_OR_NEWER
60 //Enable unity profiling for this thread
61 Profiler.BeginThreadProfiling("LeapCSharp", eventData.threadName);
62
63 //Assume that threads are not stopping and starting frequently
64 //so we can get away with less-than-optimal strategies when starting a thread.
65 //in this case we use a naive queue with a lock.
66 lock (_samplersToCreate) {
67 foreach (var blockName in eventData.blockNames) {
68 _samplersToCreate.Enqueue(blockName);
69 }
70
71 Interlocked.Add(ref _samplersToCreateCount, eventData.blockNames.Length);
72 }
73#else
74 Debug.LogWarning("Thread Profiling is unavailable in versions of Unity below 2017.3");
75#endif
76 }
77
78 public static void EndProfilingForThread(EndProfilingForThreadArgs eventData) {
79#if UNITY_2017_3_OR_NEWER
80 Profiler.EndThreadProfiling();
81#else
82 Debug.LogWarning("Thread Profiling is unavailable in versions of Unity below 2017.3");
83#endif
84 }
85
86 public static void BeginProfilingBlock(BeginProfilingBlockArgs eventData) {
87 //Sampler might not have been created yet because samplers can only be created
88 //on the main thread. We will simply not be able to report all blocks until
89 //a sampler is available.
90
91 //Note that the Dictionary type is thread safe for read operations
92 //Dictionary is only used once and so there is no risk of the dictionary
93 //being swapped out from underneath us
94
95 CustomSampler sampler;
96 if (_samplers.TryGetValue(eventData.blockName, out sampler)) {
97 sampler.Begin();
98 }
99 }
100
101 public static void EndProfilingBlock(EndProfilingBlockArgs eventData) {
102 CustomSampler sampler;
103 if (_samplers.TryGetValue(eventData.blockName, out sampler)) {
104 sampler.End();
105 }
106 }
107 }
108}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19