Перейти к основному содержимому

ProfilerMarkers

Маркеры профилировщика одной строкой, без полей и имён, которые приходится поддерживать вручную.

Быстрый старт​

До — Unity APIПосле — FastTools
private static readonly
ProfilerMarker _marker =
new("FlockSimulation.Step");

public void Step()
{
using var _ = _marker.Auto();
Integrate();
}
public void Step()
{
using var _ = this.Marker();
Integrate();
}

Marker()​

Имя маркера собирается из типа, метода и номера строки вызова:

Где вызван this.Marker()Имя маркера
void Step()FlockSimulation.Step (строка)
FlockSimulation()FlockSimulation.Ctor (строка)
float Speed { get; }FlockSimulation.Speed (строка)
Agent this[int i] { get; }FlockSimulation.Indexer (строка)
event Action ChangedFlockSimulation.Changed (строка)
class FlockSimulation.Agent { void Move() }Agent.Move (строка)
class Worker<T> { void Run() }Worker<Int32>.Run (строка)
Worker<Single>.Run (строка)
struct Job<T> { void Execute() }Job<T>.Execute (строка) для любого T
void Run<T>()FlockSimulation.Run (строка) для любого T

WithName()​

.WithName("Steering") заменяет в имени маркера метод на свой текст: FlockSimulation.Step (5) → FlockSimulation.Steering (5).

public void Step()
{
using var _ = this.Marker();

using (this.Marker().WithName("Steering"))
{
foreach (var agent in _agents)
{
using (this.Marker().WithName("Steering.Agent"))
ComputeSteering(agent);
}
}

using (this.Marker().WithName("Integrate"))
Integrate();
}
примечание

Работает только строковый литерал: имя генератор читает из исходника. С переменной, const, nameof или $"Agent {index}" останется имя метода, а аргумент всё равно будет вычисляться при каждом вызове.

В Profiler​

На каждую точку вызова генератор создаёт одно статическое поле, поэтому замер не выделяет память.

HierarchyFrame 1284

Ограничения​

  • Номер строки в имени меняется, когда вызов переезжает: сравнивайте захваты до и после правки по имени без номера.
  • Вызов без маркера — на объекте другого типа (other.Marker()), в статическом классе, во вложенном private или protected типе: анализатор AFT0010 предупредит об этом.
  • Выброшенный замер. this.Marker(); без using начинает замер, который никогда не заканчивается, — анализатор AFT0011 предупредит об этом.
внимание

Замеры попадут в чужую строку Profiler, когда:

  • вызовы this.Marker() в разных файлах partial одного типа стоят на одной строке — они делят маркер первого из них;
  • вызов без маркера стоит на той же строке, что и вызов с маркером в типе, к которому он привязался: у other.Marker() это тип other, если тот объявлен в пространстве имён вызова или во внешнем для него, у вызова во вложенном типе — базовый тип, если тот не в глобальном пространстве имён.

Пример в пакете​

Маркеры из WithName() работают в сцене ProfilerMarkers.

Стая агентов в сцене ProfilerMarkersСтая агентов в сцене ProfilerMarkers