Skip to content

Commit ead91d9

Browse files
author
Unity Technologies
committed
com.unity.test-framework.performance@2.8.0-preview
## [2.8.0] - 2021-03-16 Add overloads to measurements for overriding sample unit Fix cases where cleanup throws an exception ## [2.7.0] - 2021-02-19 Reduce metadata overhead when running locally by caching dependencies Remove the need for link.xml Restructured documentation Fixed method measurement IterationsPerMeasurement
1 parent ccb4db0 commit ead91d9

24 files changed

+556
-225
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## [2.8.0] - 2021-03-16
4+
5+
Add overloads to measurements for overriding sample unit
6+
Fix cases where cleanup throws an exception
7+
38
## [2.7.0] - 2021-02-19
49

510
Reduce metadata overhead when running locally by caching dependencies

Documentation~/measure-frames.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Records time per frame by default and provides additional properties/methods to
66
* **DontRecordFrametime()** - disables frametime measurement.
77
* **ProfilerMarkers(...)** - sample profile markers per frame. Does not work for deep profiling and `Profiler.BeginSample()`
88
* **SampleGroup(string name)** - name of the measurement, defaults to "Time" if unspecified.
9-
* **Scope()** - measures frame times in a given coroutine scope.
9+
* **Scope()** - measures frame times in a given coroutine scope. By default it uses a SampleGroup named "Time" with Milliseconds as measurement unit. You can also create your own SampleGroup, specifying a custom name and the measurement unit you want your results in, see [example 5](#example-5-specify-custom-samplegroup-in-the-scope).
1010

1111

1212
#### Example 1: Simple frame time measurement using default values of at least 7 frames and default WarmupCount (see description above).
@@ -67,3 +67,34 @@ public IEnumerator Test()
6767
.Run();
6868
}
6969
```
70+
#### Example 5: Specify Custom SampleGroup in the Scope
71+
72+
``` csharp
73+
[UnityTest, Performance]
74+
public IEnumerator Test()
75+
{
76+
var sg = new SampleGroup("MarkerName", SampleUnit.Second);
77+
using (Measure.Frames().Scope(sg))
78+
{
79+
yield return ...;
80+
}
81+
}
82+
```
83+
84+
#### Example 6: Sample profile markers per frame with custom SampleGroups that change sample unit
85+
86+
``` csharp
87+
[UnityTest, Performance]
88+
public IEnumerator Test()
89+
{
90+
var sampleGroup = new SampleGroup("Name", SampleUnit.Milliseconds);
91+
var profileMarkersSampleGroups = new []{
92+
new SampleGroup("MarkerName", SampleUnit.Second),
93+
new SampleGroup("MarkerName1", SampleUnit.Nanosecond)
94+
};
95+
96+
yield return Measure.Frames().SampleGroup(sg).ProfilerMarkers(profileMarkersSampleGroups).Run();
97+
98+
...
99+
}
100+
```

Documentation~/measure-method.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Executes the provided method, sampling performance using the following additiona
55
* **MeasurementCount(int n)** - number of measurements to capture, defaults to 9 if not specified.
66
* **IterationsPerMeasurement(int n)** - number of method executions per measurement to use. If this value is not specified, the method is executed as many times as possible until approximately 100 ms has elapsed.
77
* **SampleGroup(string name)** - name of the measurement, defaults to "Time" if unspecified.
8+
* **SampleGroup(SampleGroup sampleGroup)** - a sample group with a custom name and measurement unit. This will override the otherwise default value of "Time".
89
* **GC()** - if specified, measures the total number of Garbage Collection allocation calls.
910
* **SetUp(Action action)** - is called every iteration before method execution. Setup time is not measured.
1011
* **CleanUp(Action action)** - is called every iteration after method execution. Cleanup time is not measured.
@@ -22,7 +23,7 @@ public void Test()
2223

2324
#### Example 2: Customize Measure.Method properties
2425

25-
```
26+
``` csharp
2627
[Test, Performance]
2728
public void Test()
2829
{
@@ -36,3 +37,15 @@ public void Test()
3637
.Run();
3738
}
3839
```
40+
41+
#### Example 3: Measure.Method, SampleGroup and ProfilerMarkers
42+
43+
``` csharp
44+
[Test, Performance]
45+
public void Test()
46+
{
47+
var sg = new SampleGroup("Name", SampleUnit.Microsecond);
48+
var sgMarker = new SampleGroup("MarkerName", SampleUnit.Seconds);
49+
Measure.Method(() => { ... }).SampleGroup(sg).ProfilerMarkers(sgMarker).Run();
50+
}
51+
```

Documentation~/measure-profile-markers.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Used to record profiler markers. Profiler marker timings are recorded automatically and sampled within the scope of the `using` statement. Names should match profiler marker labels. Profiler markers are sampled once per frame. Sampling the same profiler marker per frame will result in the sum of all invocations. Note that deep and editor profiling is not available. Profiler markers created using `Profiler.BeginSample()` are not supported, switch to `ProfilerMarker` if possible.
44

5+
You can also create your own SampleGroups, specifying a custom name and the measurement units you want your results in, see [example 2](#example-2-measuring-profiler-markers-in-a-scope-with-custom-samplegroups).
6+
57
#### Example: Measuring profiler markers in a scope
68

79
``` csharp
@@ -22,3 +24,23 @@ public void Test()
2224
}
2325
}
2426
```
27+
28+
#### Example 2: Measuring profiler markers in a scope with custom SampleGroups
29+
30+
``` csharp
31+
32+
[UnityTest, Performance]
33+
public IEnumerator Test()
34+
{
35+
var sampleGroups = new []{
36+
new SampleGroup("Instantiate", SampleUnit.Second),
37+
new SampleGroup("Instantiate.Copy", SampleUnit.Nanosecond),
38+
new SampleGroup("Instantiate.Awake", SampleUnit.Microsecond)
39+
};
40+
41+
using (Measure.ProfilerMarkers(sampleGroups))
42+
{
43+
...
44+
}
45+
}
46+
```

Documentation~/measure-scope.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Measure.Scope(string name = "Time")
22

33
Measures execution time for the scope as a single time, for both synchronous and coroutine methods. Passing the name argument overrides the name of the created SampleGroup.
4+
The defualt SampleGroup is named "Time" and with Milliseconds as measurement unit. You can also create your own SampleGroup, specifying a custom name and the measurement unit you want your results in, see [example 2](#example-2-specify-custom-samplegroup).
45

5-
#### Example: Measuring a scope; execution time is measured for everything in the using statement
6+
#### Example 1: Measuring a scope; execution time is measured for everything in the using statement
67

78
``` csharp
89
[Test, Performance]
@@ -14,3 +15,17 @@ public void Test()
1415
}
1516
}
1617
```
18+
19+
#### Example 2: Specify Custom SampleGroup
20+
21+
``` csharp
22+
[Test, Performance]
23+
public void Test()
24+
{
25+
var sampleGroup = new SampleGroup("Scope", SampleUnit.Microsecond);
26+
using (Measure.Scope(sg))
27+
{
28+
...
29+
}
30+
}
31+
```

Editor/TestRunBuilder.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,14 @@ static List<string> GetPackageDependencies()
7676

7777
public void Cleanup()
7878
{
79-
if (File.Exists(Utils.TestRunPath))
80-
{
81-
File.Delete(Utils.TestRunPath);
82-
File.Delete(Utils.TestRunPath + ".meta");
83-
}
79+
if (File.Exists(Utils.TestRunPath)) { File.Delete(Utils.TestRunPath); }
80+
const string metaPath = Utils.TestRunPath + ".meta";
81+
if (File.Exists(metaPath)) {File.Delete(metaPath);}
8482

8583
if (EditorPrefs.GetBool(cleanResources) && Directory.Exists("Assets/Resources"))
8684
{
8785
Directory.Delete("Assets/Resources/", true);
88-
File.Delete("Assets/Resources.meta");
86+
if(File.Exists("Assets/Resources.meta")) {File.Delete("Assets/Resources.meta");}
8987
}
9088

9189
AssetDatabase.Refresh();

Runtime/Measure.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Diagnostics;
33
using Unity.PerformanceTesting.Exceptions;
44
using Unity.PerformanceTesting.Measurements;
5+
using Unity.PerformanceTesting.Runtime;
56
using UnityEngine;
67
using Object = UnityEngine.Object;
78

@@ -48,11 +49,21 @@ public static ScopeMeasurement Scope(string name = "Time")
4849
{
4950
return new ScopeMeasurement(name);
5051
}
52+
53+
public static ScopeMeasurement Scope(SampleGroup sampleGroup)
54+
{
55+
return new ScopeMeasurement(sampleGroup);
56+
}
5157

5258
public static ProfilerMeasurement ProfilerMarkers(params string[] profilerMarkerLabels)
5359
{
5460
return new ProfilerMeasurement(profilerMarkerLabels);
5561
}
62+
63+
public static ProfilerMeasurement ProfilerMarkers(params SampleGroup[] sampleGroups)
64+
{
65+
return new ProfilerMeasurement(sampleGroups);
66+
}
5667

5768
public static MethodMeasurement Method(Action action)
5869
{
@@ -70,24 +81,30 @@ public struct ScopeMeasurement : IDisposable
7081
private readonly SampleGroup m_SampleGroup;
7182
private readonly long m_StartTicks;
7283

73-
public ScopeMeasurement(string name)
84+
public ScopeMeasurement(SampleGroup sampleGroup)
7485
{
75-
m_SampleGroup = PerformanceTest.GetSampleGroup(name);
86+
m_SampleGroup = PerformanceTest.GetSampleGroup(sampleGroup.Name);
7687
if (m_SampleGroup == null)
7788
{
78-
m_SampleGroup = new SampleGroup(name);
89+
m_SampleGroup = sampleGroup;
7990
PerformanceTest.Active.SampleGroups.Add(m_SampleGroup);
8091
}
8192

8293
m_StartTicks = Stopwatch.GetTimestamp();
8394
PerformanceTest.Disposables.Add(this);
8495
}
8596

97+
public ScopeMeasurement(string name) : this(new SampleGroup(name))
98+
{
99+
}
100+
86101
public void Dispose()
87102
{
88103
var elapsedTicks = Stopwatch.GetTimestamp() - m_StartTicks;
89104
PerformanceTest.Disposables.Remove(this);
90105
var delta = TimeSpan.FromTicks(elapsedTicks).TotalMilliseconds;
106+
107+
delta = Utils.ConvertSample(SampleUnit.Millisecond, m_SampleGroup.Unit, delta);
91108

92109
Measure.Custom(m_SampleGroup, delta);
93110
}
@@ -97,15 +114,15 @@ public struct ProfilerMeasurement : IDisposable
97114
{
98115
private readonly ProfilerMarkerMeasurement m_Test;
99116

100-
public ProfilerMeasurement(string[] profilerMarkers)
117+
public ProfilerMeasurement(SampleGroup[] sampleGroups)
101118
{
102-
if (profilerMarkers == null)
119+
if (sampleGroups == null)
103120
{
104121
m_Test = null;
105122
return;
106123
}
107124

108-
if (profilerMarkers.Length == 0)
125+
if (sampleGroups.Length == 0)
109126
{
110127
m_Test = null;
111128
return;
@@ -115,10 +132,14 @@ public ProfilerMeasurement(string[] profilerMarkers)
115132
if (Application.isPlaying) Object.DontDestroyOnLoad(go);
116133
go.hideFlags = HideFlags.HideAndDontSave;
117134
m_Test = go.AddComponent<ProfilerMarkerMeasurement>();
118-
m_Test.AddProfilerSample(profilerMarkers);
135+
m_Test.AddProfilerSampleGroup(sampleGroups);
119136
PerformanceTest.Disposables.Add(this);
120137
}
121138

139+
public ProfilerMeasurement(string[] profilerMarkers): this(Utils.CreateSampleGroupsFromMarkerNames(profilerMarkers))
140+
{
141+
}
142+
122143
public void Dispose()
123144
{
124145
PerformanceTest.Disposables.Remove(this);
@@ -127,4 +148,4 @@ public void Dispose()
127148
Object.DestroyImmediate(m_Test.gameObject);
128149
}
129150
}
130-
}
151+
}

Runtime/Measurements/FramesMeasurement.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Diagnostics;
4+
using Unity.PerformanceTesting.Runtime;
45
using UnityEngine;
56
using Debug = UnityEngine.Debug;
67
using Object = UnityEngine.Object;
@@ -14,22 +15,34 @@ public class FramesMeasurement
1415
private const int k_ProbingMultiplier = 4;
1516
private const int k_MinIterations = 7;
1617

17-
private string[] m_ProfilerDefinitions;
18-
private string m_SampleGroup = "Time";
18+
private SampleGroup[] m_ProfilerSampleGroups;
19+
private SampleGroup m_SampleGroup = new SampleGroup("FrameTime");
1920
private int m_DesiredFrameCount;
2021
private int m_Executions;
2122
private int m_Warmup = -1;
2223
private bool m_RecordFrametime = true;
2324

2425
public FramesMeasurement ProfilerMarkers(params string[] profilerMarkerNames)
2526
{
26-
m_ProfilerDefinitions = profilerMarkerNames;
27+
m_ProfilerSampleGroups = Utils.CreateSampleGroupsFromMarkerNames(profilerMarkerNames);
28+
return this;
29+
}
30+
31+
public FramesMeasurement ProfilerMarkers(params SampleGroup[] sampleGroups)
32+
{
33+
m_ProfilerSampleGroups = sampleGroups;
2734
return this;
2835
}
2936

3037
public FramesMeasurement SampleGroup(string name)
3138
{
32-
m_SampleGroup = name;
39+
m_SampleGroup.Name = name;
40+
return this;
41+
}
42+
43+
public FramesMeasurement SampleGroup(SampleGroup sampleGroup)
44+
{
45+
m_SampleGroup = sampleGroup;
3346
return this;
3447
}
3548

@@ -51,11 +64,14 @@ public FramesMeasurement DontRecordFrametime()
5164
return this;
5265
}
5366

54-
public ScopedFrameTimeMeasurement Scope(string name = "FrameTime")
67+
public ScopedFrameTimeMeasurement Scope(string name = "Time")
5568
{
5669
return new ScopedFrameTimeMeasurement(name);
5770
}
58-
71+
public ScopedFrameTimeMeasurement Scope(SampleGroup sampleGroup)
72+
{
73+
return new ScopedFrameTimeMeasurement(sampleGroup);
74+
}
5975
public IEnumerator Run()
6076
{
6177
if (m_Executions == 0 && m_Warmup >= 0)
@@ -67,7 +83,7 @@ public IEnumerator Run()
6783
yield return m_Warmup > -1 ? WaitFor(m_Warmup) : GetDesiredIterationCount();
6884
m_DesiredFrameCount = m_Executions > 0 ? m_Executions : m_DesiredFrameCount;
6985

70-
using (Measure.ProfilerMarkers(m_ProfilerDefinitions))
86+
using (Measure.ProfilerMarkers(m_ProfilerSampleGroups))
7187
{
7288
for (var i = 0; i < m_DesiredFrameCount; i++)
7389
{
@@ -132,14 +148,17 @@ public struct ScopedFrameTimeMeasurement : IDisposable
132148
{
133149
private readonly FrameTimeMeasurement m_Test;
134150

135-
public ScopedFrameTimeMeasurement(string sampleGroup)
151+
public ScopedFrameTimeMeasurement(SampleGroup sampleGroup)
136152
{
137153
var go = new GameObject("Recorder");
138154
if (Application.isPlaying) Object.DontDestroyOnLoad(go);
139155
m_Test = go.AddComponent<FrameTimeMeasurement>();
140-
m_Test.SampleGroup = new SampleGroup(sampleGroup);
156+
m_Test.SampleGroup = sampleGroup;
141157
PerformanceTest.Disposables.Add(this);
142158
}
159+
public ScopedFrameTimeMeasurement(string name): this(new SampleGroup(name))
160+
{
161+
}
143162

144163
public void Dispose()
145164
{

0 commit comments

Comments
 (0)