Skip to content

Commit 5c1040c

Browse files
test(audience-sample): capture player-side profile on Linux PlayMode runs
Adds PlayerProfilerLogger gated on UNITY_STANDALONE_LINUX and the AUDIENCE_PLAYER_PROFILE_PATH env var. At BeforeSceneLoad inside the test player process, points UnityEngine.Profiling.Profiler at the configured path and starts a binary log of every captured frame. PR #764 captured a deep profile of the editor process. The actual test loop runs in a separate PlayerWithTests subprocess that the editor launches and waits on. The editor profile only showed roughly 86 sec of editor activity over a 27 min cell, the rest being editor idle waiting on the player. This hook plugs that gap. Wires the env var through the playmode-linux job's docker run and adds player-profile.raw to the upload-artifact path so the capture is downloadable for offline analysis in Unity Editor. Note: enables regular profiling, not deep. Deep profiling on the player would need -deepprofiling on the player command line, which Unity Test Framework does not expose for editor-launched test players. Regular profiling still surfaces per-frame CPU and the function hot list, which is what we need to identify what is eating roughly 37 sec per test.
1 parent 2d03ea7 commit 5c1040c

3 files changed

Lines changed: 79 additions & 0 deletions

File tree

.github/workflows/test-audience-sample-app.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ jobs:
468468
AUDIENCE_SCRIPTING_BACKEND: ${{ matrix.backend }}
469469
UNITY_VERSION: ${{ matrix.unity }}
470470
AUDIENCE_LINUX_GLCORE_ONLY: "1"
471+
AUDIENCE_PLAYER_PROFILE_PATH: "/github/workspace/artifacts/player-profile.raw"
471472
run: |
472473
set -uo pipefail
473474
mkdir -p artifacts
@@ -484,6 +485,7 @@ jobs:
484485
--env AUDIENCE_TEST_PUBLISHABLE_KEY --env AUDIENCE_SCRIPTING_BACKEND \
485486
--env AUDIENCE_TEST_RUN_ID --env AUDIENCE_TEST_CELL_ID \
486487
--env AUDIENCE_LINUX_GLCORE_ONLY \
488+
--env AUDIENCE_PLAYER_PROFILE_PATH \
487489
--volume "$PWD":/github/workspace:z \
488490
--cpus=8 --memory=30487m \
489491
"$image" \
@@ -737,6 +739,7 @@ jobs:
737739
artifacts/playmode.log
738740
artifacts/activation.log
739741
artifacts/Player-*.log
742+
artifacts/player-profile.raw
740743
examples/audience/Logs/**
741744
742745
# Mobile IL2CPP build validation — runs on GitHub-hosted Ubuntu via GameCI Docker
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#nullable enable
2+
3+
#if UNITY_STANDALONE_LINUX
4+
using System;
5+
using System.IO;
6+
using UnityEngine;
7+
using UnityEngine.Profiling;
8+
9+
namespace Immutable.Audience.Samples.SampleApp.Tests
10+
{
11+
// Linux PlayMode test player profiler hook.
12+
//
13+
// The editor profile we captured on PR #764 only covered the editor
14+
// process. The actual test loop runs in a separate PlayerWithTests
15+
// subprocess, which never had a profiler attached. This hook plugs
16+
// that gap from inside the player itself.
17+
//
18+
// Behaviour: at BeforeSceneLoad, reads AUDIENCE_PLAYER_PROFILE_PATH
19+
// from the player process env. When set, points
20+
// UnityEngine.Profiling.Profiler at that path and starts a binary
21+
// log of every captured frame. Output can be loaded into Unity
22+
// Editor: Window > Analysis > Profiler > Load Profile.
23+
//
24+
// Engages only on StandaloneLinux64 builds (gated by the #if) and
25+
// only when the env var is set (gated at runtime). Local dev builds
26+
// and other-platform CI runs are unaffected.
27+
//
28+
// Note: this enables regular profiling, not deep profiling. Deep
29+
// profiling is set at editor build time via the -deepprofiling
30+
// command line flag and cannot be toggled from runtime code. Regular
31+
// profiling still surfaces per-frame CPU breakdowns and the function
32+
// hot list, which is what we need to identify the per-frame UI
33+
// Toolkit cost (or whatever else is eating ~37 sec per test).
34+
public static class PlayerProfilerLogger
35+
{
36+
private const string PathEnvVar = "AUDIENCE_PLAYER_PROFILE_PATH";
37+
38+
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
39+
public static void Init()
40+
{
41+
var path = Environment.GetEnvironmentVariable(PathEnvVar);
42+
if (string.IsNullOrEmpty(path)) return;
43+
44+
try
45+
{
46+
var dir = Path.GetDirectoryName(path);
47+
if (!string.IsNullOrEmpty(dir))
48+
{
49+
Directory.CreateDirectory(dir);
50+
}
51+
52+
Profiler.logFile = path;
53+
Profiler.enableBinaryLog = true;
54+
Profiler.enabled = true;
55+
56+
Debug.Log($"[PlayerProfilerLogger] Profiler binary log enabled. Output: {path}");
57+
}
58+
catch (Exception ex)
59+
{
60+
Debug.LogWarning($"[PlayerProfilerLogger] Failed to enable profiler at {path}: {ex.Message}");
61+
}
62+
}
63+
}
64+
}
65+
#endif

examples/audience/Assets/SampleApp/Tests/Runtime/PlayerProfilerLogger.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)