The Unity script needs the Editor and the setup listed below. The separate C# companion practice runs in SharpRune without UnityEngine.
A performance claim needs a measured target
Performance work starts with a question that a capture can answer. Here the question is whether a controlled Update region allocates a new managed array each frame or reuses an existing buffer. The sample marks that region with SharpRune.BufferWork and avoids per-frame logging inside it. A marker makes the intended scope easier to locate; it does not automatically isolate every cost in the frame. Record the target, scripting backend, scene scenario and capture settings before comparing two runs, since changing those conditions can overwhelm the code difference under investigation.
The Unity Editor is useful for finding candidate work, but its host process, windows and instrumentation contribute overhead that differs from a deployed Player. Capture a representative development Player on the intended device as a separate check. Warm up the scene before comparing steady-state intervals, and preserve the same input and workload between variants. Deep Profile can change costs substantially, so a heavily instrumented capture is useful for locating behavior without necessarily being a trustworthy final timing estimate. Optimization conclusions need an explicit measurement context rather than an unexplained screenshot of one fast frame.
Portable C# companion: summarize supplied data
The SharpRune companion analyzes the supplied sequence 0, 4096, 0 and 2048. Their sum is 6144, division by four gives an average of 1536, and the maximum is 4096. All three results are arithmetic over literal input data. Nothing in the companion queries a profiler or measures this runtime. In particular, the number 4096 must not be cited as the measured total allocation size of Unity's int[1024]: an array also has runtime overhead, and the actual allocation sample depends on the target and instrumentation.
int[] bytesPerFrame = { 0, 4096, 0, 2048 };
Console.WriteLine(bytesPerFrame.Sum()); Console.WriteLine(bytesPerFrame.Average().ToString("0", CultureInfo.InvariantCulture)); Console.WriteLine(bytesPerFrame.Max());Unity Editor and Player: mark the controlled work
AllocationProbe.cs is the actual Unity script. Awake allocates the reusable array once, while Update selects either that buffer or a new array depending on allocateEveryFrame. The marker encloses the selection, one element write and the visible lastSample assignment. Capture a warmed-up interval with the toggle off, then compare an equivalent interval with it on and inspect GC.Alloc evidence around the named region. Repeat on the intended Player. The script contains no promised byte or timing result; a real capture must establish those values for its actual backend.
private void Update()
{
using (WorkMarker.Auto())
{
int[] buffer = allocateEveryFrame ? new int[1024] : reusable;
buffer[0] = Time.frameCount;
lastSample = buffer[0];
}
}Allocation volume is not collection duration
Several different quantities can move independently: bytes allocated during an interval, live managed data afterward, native engine memory and time spent collecting. A reduction in one does not prove an equal reduction in the others. Likewise, a zero-allocation steady-state path can still be slow because of CPU work, physics or rendering. Avoid adding Debug.Log to every measured frame merely to prove the loop runs, since formatting and logging can create unrelated work. Keep initialization allocations outside the steady-state comparison and report occasional spikes rather than hiding them behind one favorable average.
Two independent profiling investigations
First, independently vary the number of observed frames in the console data exercise. Append another zero sample and predict a new sum of 6144, maximum of 4096 and rounded average output of 1229 with the existing zero-decimal formatting. Hint: the sum stays constant while the denominator becomes five; the exact mean is 1228.8 before formatting. This is a statistics exercise, not profiling. Explain why reporting only the average would hide the single 4096-byte sample even if those inputs had come from a real capture.
Second, create a separate Player capture plan for the two AllocationProbe settings. Use one object, the same scene and a fixed observation interval after warm-up; record device, backend, development flags and profiling settings. Hint: compare the named work region and GC.Alloc samples first, then inspect frame timing and collection activity separately. Repeat the comparison to check that an isolated spike is not the whole conclusion. Do not assert that turning the toggle off removes all allocations from the application, because other systems remain outside this controlled probe's ownership.
Review a reproducible measurement record
A useful performance note states the question, controlled change, target conditions and observed result, followed by its limits. Preserve both capture variants so another person can inspect the same region instead of trusting a general statement that pooling or reuse is always faster. The portable totals remain supplied-data arithmetic, while the Unity script establishes a concrete allocation experiment. Keep initialization, steady-state allocation and collection timing distinct; measure the intended Player before turning Editor observations into a product claim or spending effort on an unmeasured optimization.
- Label the target, backend and capture settings.
- Warm up before comparing the same marked region.
- Distinguish supplied statistics from observed GC.Alloc evidence.
- Report allocations, retained memory and collection time separately.
Unity Editor example
Set up in Unity 6
- Attach AllocationProbe.cs to one object and open Window > Analysis > Profiler > CPU Usage.
- Enter Play mode, allow initialization to finish and locate SharpRune.BufferWork in a captured interval.
- Compare allocateEveryFrame off and on over the same scenario; inspect GC.Alloc samples rather than only total frame time.
- Create a development Player and connect the Profiler to the intended device for a separate target capture.
- Record scripting backend, target, capture settings and whether Editor/Deep Profile overhead was present.
AllocationProbe.cs
Download Unity script ↗using Unity.Profiling;
using UnityEngine;
public sealed class AllocationProbe : MonoBehaviour
{
private static readonly ProfilerMarker WorkMarker = new ProfilerMarker("SharpRune.BufferWork");
[SerializeField] private bool allocateEveryFrame;
[SerializeField] private int lastSample;
private int[] reusable;
private void Awake() { reusable = new int[1024]; }
private void Update()
{
using (WorkMarker.Auto())
{
int[] buffer = allocateEveryFrame ? new int[1024] : reusable;
buffer[0] = Time.frameCount;
lastSample = buffer[0];
}
}
}
What to observe in Unity
The allocation-enabled path creates a new managed array each Update. Profiler measurements must establish the actual allocation and timing results on the chosen Player; no numeric performance claim is embedded in the script.
The console practice below isolates the C# logic. It does not run a Unity scene or emulate Unity engine callbacks.
C# companion practice
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
int[] bytesPerFrame = { 0, 4096, 0, 2048 };
Console.WriteLine(bytesPerFrame.Sum()); Console.WriteLine(bytesPerFrame.Average().ToString("0", CultureInfo.InvariantCulture)); Console.WriteLine(bytesPerFrame.Max());
C# practice output
6144 1536 4096
The portable data is supplied, not profiled; measure the real Player with the actual Unity Profiler.