Repository: Unity-Technologies/com.unity.editoriterationprofiler
Branch: master
Commit: 02a50237af74
Files: 83
Total size: 148.4 KB
Directory structure:
gitextract_9o_f0g0j/
├── .gitignore
├── CHANGELOG.md
├── CHANGELOG.md.meta
├── CONTRIBUTING.md
├── CONTRIBUTING.md.meta
├── Documentation~/
│ ├── TableOfContents.md
│ ├── editor-iteration-profiler.md
│ ├── exporting-data.md
│ └── index.md
├── Editor/
│ ├── DataCollector.cs
│ ├── DataCollector.cs.meta
│ ├── EditorIterationProfiler.API/
│ │ ├── IEditorIterationProfilerController.cs
│ │ ├── IEditorIterationProfilerController.cs.meta
│ │ ├── IEventSubscriber.cs
│ │ ├── IEventSubscriber.cs.meta
│ │ ├── IIterationList.cs
│ │ ├── IIterationList.cs.meta
│ │ ├── IProfilerDataCollector.cs
│ │ └── IProfilerDataCollector.cs.meta
│ ├── EditorIterationProfiler.API.meta
│ ├── EditorIterationProfilerAnalytics.cs
│ ├── EditorIterationProfilerAnalytics.cs.meta
│ ├── EditorIterationProfilerController.cs
│ ├── EditorIterationProfilerController.cs.meta
│ ├── EditorIterationProfilerIntegration.cs
│ ├── EditorIterationProfilerIntegration.cs.meta
│ ├── EditorIterationProfilerSettings.cs
│ ├── EditorIterationProfilerSettings.cs.meta
│ ├── EditorIterationProfilerTreeView.cs
│ ├── EditorIterationProfilerTreeView.cs.meta
│ ├── EditorIterationProfilerWindow.cs
│ ├── EditorIterationProfilerWindow.cs.meta
│ ├── EventData.cs
│ ├── EventData.cs.meta
│ ├── Formatters/
│ │ ├── Aggregator.cs
│ │ ├── Aggregator.cs.meta
│ │ ├── DataReporterProvider.cs
│ │ ├── DataReporterProvider.cs.meta
│ │ ├── DataReporters.cs
│ │ ├── DataReporters.cs.meta
│ │ ├── FileReporter.cs
│ │ ├── FileReporter.cs.meta
│ │ ├── Formatter.cs
│ │ ├── Formatter.cs.meta
│ │ ├── IndentationProvider.cs
│ │ ├── IndentationProvider.cs.meta
│ │ ├── Reporters/
│ │ │ ├── CSVReporter.cs
│ │ │ ├── CSVReporter.cs.meta
│ │ │ ├── ChromeTracingReporter.cs
│ │ │ ├── ChromeTracingReporter.cs.meta
│ │ │ ├── EditorLogReporter.cs
│ │ │ ├── EditorLogReporter.cs.meta
│ │ │ ├── HTMLPerfReport.cs
│ │ │ ├── HTMLPerfReport.cs.meta
│ │ │ ├── HTMLReporter.cs
│ │ │ ├── HTMLReporter.cs.meta
│ │ │ ├── HTMLReporterPrefix.txt
│ │ │ ├── HTMLReporterPrefix.txt.meta
│ │ │ ├── PlaintextReporter.cs
│ │ │ └── PlaintextReporter.cs.meta
│ │ └── Reporters.meta
│ ├── Formatters.meta
│ ├── IterationEventKind.cs
│ ├── IterationEventKind.cs.meta
│ ├── IterationEventRoot.cs
│ ├── IterationEventRoot.cs.meta
│ ├── IterationList.cs
│ ├── IterationList.cs.meta
│ ├── ProfilerDataCollector.cs
│ ├── ProfilerDataCollector.cs.meta
│ ├── Unity.EditorIterationProfiler.Editor.asmdef
│ ├── Unity.EditorIterationProfiler.Editor.asmdef.meta
│ ├── UnityEditorEvents.cs
│ ├── UnityEditorEvents.cs.meta
│ ├── UnityProfiling.cs
│ └── UnityProfiling.cs.meta
├── Editor.meta
├── LICENSE.md
├── LICENSE.md.meta
├── README.md
├── README.md.meta
├── package.json
└── package.json.meta
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# =============== #
# Unity generated #
# =============== #
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
[Uu]nity[Pp]ackage[Mm]anager/
[Ll]ogs/
[Pp]ackages/[Mm]icrosoft*/
*.pidb.meta
*.pdb.meta
*.mdb.meta
*.apk
*.unitypackage
*.log
app.config
packages.config
# Unity3D Generated File On Crash Reports #
sysinfo.txt
# ===================================== #
# Visual Studio / MonoDevelop / Rider etc. generated #
# ===================================== #
ExportedObj/
.consulo/
.vs/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db
.idea
# ============ #
# OS generated #
# ============ #
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to the webrtc package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.1.2-preview] - 2021-09-23
### Changed
- Deferred drawing the GUI so it pollutes the data less.
- Fixed an issue where "Domain unloader" wasn't found as it was renamed to "Domain Unloader".
## [0.1.1-preview] - 2020-10-03
### Changed
- Fixed documentation references.
- Removed square brackets from the name of the entries in this window.
## [0.1.0-preview] - 2020-06-10
- Initial Release.
================================================
FILE: CHANGELOG.md.meta
================================================
fileFormatVersion: 2
guid: 249ab3ebb372f234e98dbac31f5e3265
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement)
By making a pull request, you are confirming agreement to the terms and conditions of the UCA, including that your Contributions are your original creation and that you have complete right and authority to make your Contributions.
## Once you have a change ready following these ground rules. Simply make a pull request
================================================
FILE: CONTRIBUTING.md.meta
================================================
fileFormatVersion: 2
guid: 2b6a7b8e81611044a8d28e71c0e71043
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Documentation~/TableOfContents.md
================================================
* [About the Editor Iteration Profiler](index.md)
* [Using the Editor Iteration Profiler](editor-iteration-profiler.md)
* [Exporting data](exporting-data.md)
================================================
FILE: Documentation~/editor-iteration-profiler.md
================================================
# Using the Editor Iteration Profiler
Once you’ve installed the Editor Iteration Profiler, navigate to __Window > Analysis > Editor Iteration Profiler > Show Window__. This opens the EIP in its own window.
 <br/>
*The Editor Iteration profiler window*
## Editor Iteration Profiler controls
The controls for the EIP are in the toolbar at the top of the window. You can use these controls to navigate through the data and export it.
|**Control**|**Function**|
|---|---|
|**Enable**|Enables the Editor Iteration Profiler and starts collecting data. When you select this button, the EIP also enables the Profiler and sets it to run with the __Editor__ as its profiling target.|
|**Deep Profile**|Collects all information on managed calls. For more information on deep profiling, see the documentation on the [Profiler window](https://docs.unity3d.com/Manual/ProfilerWindow.html#deep-profiling).|
|**Flatten**|Collapses events in the table that contain multiple parent items with one child. This is useful if you are investigating GUI code or have performed Deep Profiling.|
|**User Code**|Filters out Unity engine code and displays information related to your own code.|
|**Clear**|Removes all recorded events from the EIP.|
|**Collapse All**|Recursively collapses all events in the table.|
|**Print to Console**|Logs all data to the console in a plain text format.|
|**Export**|Export all of the data in the EIP. You can choose from HTML, JSON, CSV, Plaintext, or HTML Performance Report. For more information on this see the documentation on [Exporting data](exporting-data.md).|
|**Export Profiler Data**|Export the data in the EIP for the selected Profiler frame, or choose a range of Profiler frames to export the EIP data for. When you select **Multiple Frames**, the beginning and end limits are inclusive. For more information, see the documentation on [How to export data](exporting-data#how-to-export-data.md)|
================================================
FILE: Documentation~/exporting-data.md
================================================
# Exporting Data
You can export the data that the Editor Iteration Profiler captures in several different file formats so that you can inspect the performance of your application in greater detail. The following file formats are available:
* [.html](exporting-data#html.md)
* [.json](exporting-data#json.md) (for [chrome tracing](http://www.chromium.org/developers/how-tos/trace-event-profiling-tool))
* [.csv](exporting-data#csv.md)
* [Plain text](exporting-data#plain-text.md)
* [HTML Performance Report](exporting-data#html-report.md)
<a name="how-to"></a>
## How to export data
To export all of the data that the EIP has captured, select __Export__ in the toolbar at the top of the EIP window, and then choose the format you want to export the data in. The EIP then displays a Save dialog box, where you can choose where to save the data to.
To export the data that the EIP has captured for a particular frame in the Profiler, select that frame in the Profiler window. Then in the EIP window’s toolbar, select __Export Profiler Data > Export Selected Frame__ and choose the format you’d like to export the data to. The EIP then displays a Save dialog box, where you can choose where to save the data to.
You can also export the data the EIP has captured for a range of Profiler frames. To do this, select __Export Profiler Data > Multiple Frames__ in the EIP window’s toolbar, and then choose the format you’d like to export the data to. The EIP then displays a dialog box that you can use to set the beginning and end range for the frames you want to export the data for.
 <br/>
*The frame range selector dialog box*
Select the __Export__ button and then the EIP displays a Save dialog box where you can choose where to save the data to.
<a name="html"></a>
## HTML export option
The __HTML__ export option exports the EIP data to a .html format that you can then open in a web browser and inspect further. It contains the same data in the EIP window, but also displays a percentage of how much time was spent on each event.
 <br/>
*EIP data in HTML format*
> [!NOTE]
> Events in square brackets are leaf items without any children.
<a name="json"></a>
## JSON export option
The __JSON__ export option exports the EIP data to a .json format, which you can then use to visualize the data with the [Chrome Tracing](http://www.chromium.org/developers/how-tos/trace-event-profiling-tool) tool. To use Chrome Tracing, go to `chrome://tracing` in a Chromium-based web browser(Google Chrome, Microsoft Edge Chromium, Opera, etc.), and then import the .json file.
 <br/>
*EIP data in .json format imported into Chrome Tracing*
<a name="csv"></a>
## CSV export option
The __CSV__ export option exports the EIP data to a .csv format which you can then use to import the data into other programs, such as Excel or a Python library.
> [!NOTE]
>This file contains a header in which environment information is stored (system specs, date etc.)
<a name="plain-text"></a>
## Plaintext export option
The __Plaintext__ export option exports the EIP data into a plain text file format. This is the same data that you can display in the console if you select __Print to Console__ button in the EIP window’s toolbar. It also gives you the option to isolate the data and remove other information which is in the `Editor.log` file.
<a name="html-report"> </a>
## HTML Performance Report export option
The __HTML Performance Report__ displays the EIP data in a similar way to the HTML export option, but additionally groups together information and also reduces the number of levels you need to click through to get to important information.
 <br/>
*HTML Performance Report view*
Items in curly brackets `{}` represent items that have children that the EIP hid because the parents were under the minimum set threshold, which is currently set to a hard-coded value of 1%.
The colored items represent ‘buckets’ of similar data, which the EIP groups in one place for convenience. The EIP does not add the total time of these to the original time, and it gives an estimate for that iteration.
================================================
FILE: Documentation~/index.md
================================================
# About Editor Iteration Profiler
The Editor Iteration Profiler (EIP) is a tool that you can use alongside [Unity's built-in Profiler](https://docs.unity3d.com/Manual/Profiler.html) to monitor Editor iteration (domain reload) times. It helps you to understand why Unity takes a long time to compile your scripts or enter Play Mode.
An iteration is a process that contains instructions that it repeats until a condition is met. Unity relies on a variety of iteration types. The EIP uses the data from the Profiler to monitor iterations that relate to the scripting side of Unity, specifically:
* Entering and exiting Play Mode
* Assembly reloads
* Script compilations
During these iterations, the Profiler also monitors Asset import time.
The EIP saves all of this information in a separate window which you can then use to navigate through the data the Profiler produces. What’s more, the data that the EIP collects persists for the lifetime of the Editor, unlike the built-in Profiler which is limited to storing a set number of frames.
You can then [export the captured data](exporting-data.md) to either HTML, JSON, CSV, or plain text format. In addition to these formats, you can export the data to a HTML Performance Report, which groups the data together to make it easier to see areas you can optimize.
## Preview package
This package is available as a preview, so it is not ready for production use. The features and documentation in this package might change before it is verified for release.
## Package contents
The following table describes the package folder structure:
|**Location**|**Description**|
|---|---|
|`Editor`| Contains the code for this package.|
|`Documentation~`| Contains the documentation for the package.|
## Installation
To install this package, perform the following steps:
* Download the repository from GitHub
* Place it into your Project’s `Packages` folder
## Requirements
This version of Editor Iteration Profiler is compatible with the following versions of the Unity Editor:
* 2019.3 and later
## Known limitations
The Editor Iteration Profiler package has the following known limitations:
* During Deep Profiling the system might run out of memory and freeze the whole Editor for extended periods of time, especially in large Projects.
* If the script compilation taxes more than 600 frames, the EIP might not capture all data.
## Feedback and troubleshooting
Please report bugs/suggestions at https://github.com/Unity-Technologies/com.unity.editoriterationprofiler/issues .
If you encounter any problems with the EIP, either select the __Clear__ button in the toolbar of the EIP window, or go to __Window > Analysis > Editor Iteration Profiler > Purge Cache__ to clear the EIP’s cache. This usually resolves most issues.
================================================
FILE: Editor/DataCollector.cs
================================================
using System;
using UnityEditor.EditorIterationProfiler.API;
using UnityEngine.Assertions;
namespace UnityEditor.EditorIterationProfiler
{
[Serializable]
class DataCollector : IEventSubscriber
{
IIterationList m_IterationList;
IProfilerDataCollector m_ProfilerDataCollector;
public DataCollector(IProfilerDataCollector profilerCollector, IIterationList iterationList)
{
Initialize(profilerCollector, iterationList);
}
void Initialize(IProfilerDataCollector profilerCollector, IIterationList iterationList)
{
m_IterationList = iterationList;
m_ProfilerDataCollector = profilerCollector;
}
public void Subscribe()
{
UnityEditorEvents.Subscribe();
UnityEditorEvents.EditorEvent += EditorEvent;
}
public void Unsubscribe()
{
UnityEditorEvents.Unsubscribe();
UnityEditorEvents.EditorEvent -= EditorEvent;
}
void EditorEvent(UnityEditorEvents.Event evt, string data)
{
Assert.IsNotNull(m_IterationList);
if (!UnityProfiling.EditorProfilingEnabled)
{
return;
}
//Debug.Log($"EditorEvent: {evt} {data}");
switch (evt)
{
case UnityEditorEvents.Event.ScriptCompilationStarted:
{
m_IterationList.NewIteration(IterationEventKind.ScriptCompilation);
var assetImportEvent = m_IterationList.LastIterationEventRoot.StartEvent(IterationEventKind.AssetImport);
m_ProfilerDataCollector.Collect(IterationEventKind.AssetImport, m_IterationList.LastIterationEventRoot, assetImportEvent);
var scriptCompilationEvent = m_IterationList.LastIterationEventRoot.StartEvent(IterationEventKind.ScriptCompilation);
scriptCompilationEvent.SetStartTime();
break;
}
case UnityEditorEvents.Event.ScriptCompilationFinished:
{
m_IterationList.LastIterationEventRoot.FinishEvent(IterationEventKind.ScriptCompilation);
break;
}
case UnityEditorEvents.Event.AssemblyCompilationStarted:
{
var eventData = m_IterationList.LastIterationEventRoot.StartEvent(IterationEventKind.AssemblyCompilation, data, null);
m_IterationList.LastIterationEventRoot.SetParent(eventData, IterationEventKind.ScriptCompilation);
//m_ProfilerDataCollector.Collect(IterationEventKind.AssemblyCompilationStart, m_IterationList.LastIterationEventRoot, eventData);
eventData.SetStartTime();
break;
}
case UnityEditorEvents.Event.AssemblyCompilationFinished:
{
//var ev = m_IterationList.LastIterationEventRoot.FindLastEvent(IterationEventKind.ScriptCompilation);
//m_ProfilerDataCollector.Collect(IterationEventKind.AssemblyCompilationFinish, m_IterationList.LastIterationEventRoot, ev);
m_IterationList.LastIterationEventRoot.FinishEvent(data);
break;
}
case UnityEditorEvents.Event.AssemblyReloadStarted:
{
if (m_IterationList.LastIterationEventRoot != null)
{
var enterPlayModeEvent = m_IterationList.LastIterationEventRoot.FindLastEvent(IterationEventKind.EnterPlayMode);
// If this assembly reload is part of a enter play mode iteration,
// then do no add the event, as it happens in the same frame and
// profiling data will contain the domain reload event data.
if (enterPlayModeEvent != null)
{
return;
}
var eventData = m_IterationList.LastIterationEventRoot.StartEvent(IterationEventKind.AssemblyReload);
m_ProfilerDataCollector.Collect(IterationEventKind.AssemblyReload, m_IterationList.LastIterationEventRoot, eventData);
}
break;
}
case UnityEditorEvents.Event.AssemblyReloadFinished:
{
break;
}
case UnityEditorEvents.Event.EnteringPlayMode:
{
m_IterationList.NewIteration(IterationEventKind.EnterPlayMode);
var eventData = m_IterationList.LastIterationEventRoot.StartEvent(IterationEventKind.EnterPlayMode);
m_ProfilerDataCollector.Collect(IterationEventKind.EnterPlayMode, m_IterationList.LastIterationEventRoot, eventData);
break;
}
case UnityEditorEvents.Event.EnteredPlayMode:
{
break;
}
case UnityEditorEvents.Event.ExitingPlayMode:
{
m_IterationList.NewIteration(IterationEventKind.ExitPlayMode);
var eventData = m_IterationList.LastIterationEventRoot.StartEvent(IterationEventKind.ExitPlayMode);
m_ProfilerDataCollector.Collect(IterationEventKind.ExitPlayMode, m_IterationList.LastIterationEventRoot, eventData);
break;
}
case UnityEditorEvents.Event.ExitedPlayMode:
{
break;
}
}
}
}
}
================================================
FILE: Editor/DataCollector.cs.meta
================================================
fileFormatVersion: 2
guid: ea639bdc1b7738841a40c85658e414f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfiler.API/IEditorIterationProfilerController.cs
================================================
namespace UnityEditor.EditorIterationProfiler.API
{
public interface IEditorIterationProfilerController
{
IIterationList IterationList { get; }
IDataReporterProvider DataReporterProvider { get; }
EditorIterationProfilerSettings Settings { get; }
}
}
================================================
FILE: Editor/EditorIterationProfiler.API/IEditorIterationProfilerController.cs.meta
================================================
fileFormatVersion: 2
guid: 3b753f26d3c16a64fb73f79a76bfc62c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfiler.API/IEventSubscriber.cs
================================================
namespace UnityEditor.EditorIterationProfiler
{
public interface IEventSubscriber
{
void Subscribe();
void Unsubscribe();
}
}
================================================
FILE: Editor/EditorIterationProfiler.API/IEventSubscriber.cs.meta
================================================
fileFormatVersion: 2
guid: dfbe793476c38d545acebf95bef144a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfiler.API/IIterationList.cs
================================================
using System;
using System.Collections.Generic;
using UnityEditor.EditorIterationProfiler.Formatting;
namespace UnityEditor.EditorIterationProfiler
{
public interface IIterationList
{
List<IterationEventRoot> IterationEventRoots { get; }
IterationEventRoot LastIterationEventRoot { get; }
List<IterationEventKind> IterationEventKinds { get; }
Action<IIterationList> Updated { get; set; }
void NewIteration(IterationEventKind kind);
void NotifyUpdated();
}
}
================================================
FILE: Editor/EditorIterationProfiler.API/IIterationList.cs.meta
================================================
fileFormatVersion: 2
guid: b3881855ff94b2a419205af6f42f003b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfiler.API/IProfilerDataCollector.cs
================================================
namespace UnityEditor.EditorIterationProfiler.API
{
public interface IProfilerDataCollector : IEventSubscriber
{
void Collect(IterationEventKind iterationEventKind, IterationEventRoot iterationEventRoot, EventData rootEvent);
void Clear();
}
}
================================================
FILE: Editor/EditorIterationProfiler.API/IProfilerDataCollector.cs.meta
================================================
fileFormatVersion: 2
guid: a368e7eb7b9059c429c7bb9837c8f3fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfiler.API.meta
================================================
fileFormatVersion: 2
guid: 69bdb52499db5994ca64e22a6bc04cf5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfilerAnalytics.cs
================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Analytics;
namespace UnityEditor.EditorIterationProfiler
{
class EditorIterationProfilerAnalytics
{
const string k_VendorKey = "unity.editoriterationprofiler";
static bool s_ExportEventRegistered;
static bool s_InteractionEventRegistered;
const int k_MaxEventsPerHour = 1000;
const int k_MaxNumberOfElements = 1000;
const string k_ExportEventName = "eipExport";
const string k_InteractionEventName = "eipInteraction";
static bool EnableAnalytics()
{
AnalyticsResult resultExport = EditorAnalytics.RegisterEventWithLimit(k_ExportEventName, k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey);
AnalyticsResult resultInteraction = EditorAnalytics.RegisterEventWithLimit(k_InteractionEventName, k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey);
if (resultExport == AnalyticsResult.Ok)
{
s_ExportEventRegistered = true;
}
if (resultExport == AnalyticsResult.Ok)
{
s_InteractionEventRegistered = true;
}
return s_ExportEventRegistered && s_InteractionEventRegistered;
}
internal enum ExportStatus
{
Started,
Finished,
Error
}
internal enum ExportType
{
Selected,
MultiWindow,
Multi,
Captured,
CapturedAll
}
struct ExportEventData
{
public string guid;
public string format;
public string type;
public string status;
}
struct InteractionEventData
{
public bool eipState;
public bool isPlaying;
public bool deepProfile;
public bool flatten;
public bool userCode;
}
public static void SendExportEvent(string format, string type, string status, string guid)
{
if (!UnityEngine.Analytics.Analytics.enabled || !EnableAnalytics())
{
return;
}
var data = new ExportEventData()
{
format = format,
type = type,
status = status,
guid = guid
};
EditorAnalytics.SendEventWithLimit(k_ExportEventName, data);
}
public static void SendInteractionEvent(bool state, bool isPlaying, bool deepProfile, bool flatten, bool userCode)
{
if (!UnityEngine.Analytics.Analytics.enabled || !EnableAnalytics())
{
return;
}
var data = new InteractionEventData()
{
eipState = state,
isPlaying = isPlaying,
deepProfile = deepProfile,
flatten = flatten,
userCode = userCode
};
EditorAnalytics.SendEventWithLimit(k_InteractionEventName, data);
}
}
}
================================================
FILE: Editor/EditorIterationProfilerAnalytics.cs.meta
================================================
fileFormatVersion: 2
guid: 5248670f7ba3f2c419bab949189a46bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfilerController.cs
================================================
using System.Collections.Generic;
using UnityEditor.EditorIterationProfiler.API;
using UnityEngine;
using UnityEngine.Assertions;
namespace UnityEditor.EditorIterationProfiler
{
public class EditorIterationProfilerController : ScriptableObject, IEditorIterationProfilerController
{
[SerializeField]
IterationList m_IterationList;
public IIterationList IterationList => m_IterationList;
[SerializeField]
ProfilerDataCollector m_ProfilerDataCollector;
public IProfilerDataCollector ProfilerDataCollector => m_ProfilerDataCollector;
[SerializeField]
DataReporterProvider m_DataReporterProvider;
public IDataReporterProvider DataReporterProvider => m_DataReporterProvider;
[SerializeField]
EditorIterationProfilerSettings m_Settings;
public EditorIterationProfilerSettings Settings => m_Settings;
[SerializeField]
DataCollector m_DataCollector;
public EditorIterationProfilerController()
{
m_IterationList = new IterationList();
m_ProfilerDataCollector = new ProfilerDataCollector(m_IterationList);
m_DataCollector = new DataCollector(m_ProfilerDataCollector, m_IterationList);
m_DataReporterProvider = new DataReporterProvider();
m_Settings = new EditorIterationProfilerSettings();
}
public EditorIterationProfilerController(IIterationList iterationList, IProfilerDataCollector profilerDataCollector)
{
m_IterationList = iterationList as IterationList;
m_ProfilerDataCollector = profilerDataCollector as ProfilerDataCollector;
m_DataCollector = new DataCollector(m_ProfilerDataCollector, m_IterationList);
m_DataReporterProvider = new DataReporterProvider();
m_Settings = new EditorIterationProfilerSettings();
}
void OnEnable()
{
m_DataCollector.Subscribe();
m_ProfilerDataCollector.Subscribe();
}
void OnDisable()
{
m_DataCollector.Unsubscribe();
m_ProfilerDataCollector.Unsubscribe();
}
internal void Initialize()
{
m_IterationList.Reload();
}
public void Clear()
{
m_IterationList.Clear();
m_ProfilerDataCollector.Clear();
}
}
}
================================================
FILE: Editor/EditorIterationProfilerController.cs.meta
================================================
fileFormatVersion: 2
guid: a7e1f201c78caea4ab211abb5ca49032
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfilerIntegration.cs
================================================
using System.Linq;
using UnityEditor.EditorIterationProfiler.API;
using UnityEngine;
using Object = UnityEngine.Object;
namespace UnityEditor.EditorIterationProfiler
{
[InitializeOnLoad]
public static class EditorIterationProfilerIntegration
{
static EditorIterationProfilerController s_Instance;
public static IEditorIterationProfilerController Instance
{
get
{
if (s_Instance != null)
{
return s_Instance;
}
FindOrCreateInstance();
return s_Instance;
}
}
static EditorIterationProfilerIntegration()
{
EditorApplication.delayCall += Initialize;
}
internal static void Initialize()
{
FindOrCreateInstance();
}
static void FindOrCreateInstance()
{
EditorIterationProfilerController[] instances = Resources.FindObjectsOfTypeAll<EditorIterationProfilerController>();
if (instances != null)
{
s_Instance = instances.FirstOrDefault();
}
if (s_Instance == null)
{
s_Instance = ScriptableObject.CreateInstance<EditorIterationProfilerController>();
s_Instance.hideFlags = HideFlags.DontSave;
}
s_Instance.Initialize();
}
public static void Clear()
{
s_Instance.Clear();
}
[MenuItem("Window/Analysis/Editor Iteration Profiler/Purge Caches", priority = 21)]
public static void PurgeScriptableObjects()
{
Debug.Log("Caches Purged!", s_Instance);
if (s_Instance != null)
{
Clear();
}
EditorIterationProfilerController[] instances = Resources.FindObjectsOfTypeAll<EditorIterationProfilerController>();
foreach (var instance in instances)
{
Object.DestroyImmediate(instance);
}
FindOrCreateInstance();
}
}
}
================================================
FILE: Editor/EditorIterationProfilerIntegration.cs.meta
================================================
fileFormatVersion: 2
guid: 9920ea31757240744bbf4d4b9c7f9f14
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfilerSettings.cs
================================================
using System;
using System.Text;
using UnityEditor.Compilation;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler.API
{
[Serializable]
public class EditorIterationProfilerSettings
{
[field: SerializeField]
public bool DeepProfile { get; set; }
[field: SerializeField]
public bool Flatten { get; set; }
[field: SerializeField]
public bool UserCode { get; set; }
internal string UnityVersion => Application.unityVersion;
internal string ProductName => PlayerSettings.productName;
internal string Time => DateTime.UtcNow + " UTC";
internal bool FastEnterPlayMode => EditorSettings.enterPlayModeOptionsEnabled;
internal string Platform => Application.platform.ToString();
#if UNITY_2020_OR_NEWER
internal string CodeOptimization => CompilationPipeline.codeOptimization.ToString();
#endif
internal string SystemInfo => UnityEngine.SystemInfo.processorType.TrimEnd() + "; " + UnityEngine.SystemInfo.systemMemorySize / 1000 + " GB RAM";
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"Time: {EditorIterationProfilerIntegration.Instance.Settings.Time}");
sb.AppendLine($"Unity Version: {EditorIterationProfilerIntegration.Instance.Settings.UnityVersion}");
sb.AppendLine($"Platform: {EditorIterationProfilerIntegration.Instance.Settings.Platform}");
sb.AppendLine($"System Specs: {EditorIterationProfilerIntegration.Instance.Settings.SystemInfo}");
sb.AppendLine($"Product Name: {EditorIterationProfilerIntegration.Instance.Settings.ProductName}");
sb.AppendLine($"Deep Profile: {EditorIterationProfilerIntegration.Instance.Settings.DeepProfile}");
sb.AppendLine($"Flatten: {EditorIterationProfilerIntegration.Instance.Settings.Flatten}");
sb.AppendLine($"User Code: {EditorIterationProfilerIntegration.Instance.Settings.UserCode}");
sb.AppendLine($"Fast EnterPlayMode: {EditorIterationProfilerIntegration.Instance.Settings.FastEnterPlayMode}");
#if UNITY_2020_OR_NEWER
sb.Append($"Editor Code Optimization: {EditorIterationProfilerIntegration.Instance.Settings.CodeOptimization}");
#endif
return sb.ToString();
}
}
}
================================================
FILE: Editor/EditorIterationProfilerSettings.cs.meta
================================================
fileFormatVersion: 2
guid: 0635b7d495ef2fa4a97e5eb88021bacf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfilerTreeView.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
using UnityEngine.Assertions;
namespace UnityEditor.EditorIterationProfiler
{
[Serializable]
class EditorIterationProfilerTreeViewItem : TreeViewItem
{
public string Details
{
get; set;
}
public double Duration
{
get; set;
}
}
public class EditorIterationProfilerTreeView : TreeView
{
enum ColumnId
{
Event,
Details,
Duration,
}
static readonly ColumnId[] k_ColumnTypes =
{
ColumnId.Event,
ColumnId.Details,
ColumnId.Duration,
};
bool m_UserCodeOnly;
public bool UserCodeOnly
{
get => m_UserCodeOnly;
set
{
m_UserCodeOnly = value;
EditorIterationProfilerIntegration.Instance.Settings.UserCode = value;
}
}
bool m_Flatten;
public bool Flatten
{
get => m_Flatten;
set
{
m_Flatten = value;
EditorIterationProfilerIntegration.Instance.Settings.Flatten = value;
}
}
public EditorIterationProfilerTreeView(TreeViewState state, MultiColumnHeader header) : base(state, header)
{
if (header == null)
{
throw new ArgumentNullException(nameof(header), "Header is null");
}
showAlternatingRowBackgrounds = true;
showBorder = true;
header.sortingChanged += OnSortingChanged;
UserCodeOnly = EditorPrefs.GetBool(EditorIterationProfilerWindow.Styles.k_UserCodePref);
Flatten = EditorPrefs.GetBool(EditorIterationProfilerWindow.Styles.k_FlattenPref);
EditorIterationProfilerIntegration.Instance.IterationList.Updated += iterationList => Reload();
Reload();
}
void OnSortingChanged(MultiColumnHeader multiColumnHeader)
{
var index = multiColumnHeader.sortedColumnIndex;
var columnTypes = k_ColumnTypes[index];
if (hasSearch)
{
//Sort(GetRows(), columnTypes, multiColumnHeader.IsSortedAscending(index));
}
else
{
//SortHierarchical(rootItem, columnTypes, multiColumnHeader.IsSortedAscending(index));
}
Reload();
}
static void Sort(IList<TreeViewItem> rows, ColumnId columnId, bool ascending)
{
if (rows == null)
{
return;
}
IList<TreeViewItem> sortedRows;
switch (columnId)
{
case ColumnId.Details:
{
sortedRows = rows.Order(x => ((EditorIterationProfilerTreeViewItem)x).Details, ascending).ToList();
break;
}
case ColumnId.Duration:
{
sortedRows = rows.Order(x => ((EditorIterationProfilerTreeViewItem)x).Duration, ascending).ToList();
break;
}
default:
{
sortedRows = rows.Order(x => ((EditorIterationProfilerTreeViewItem)x).displayName, ascending).ToList();
break;
}
}
rows.Clear();
foreach (var r in sortedRows)
{
rows.Add(r);
}
}
static void SortHierarchical(TreeViewItem root, ColumnId columnId, bool ascending = true)
{
if (root == null)
{
return;
}
SortItems(root.children, columnId, ascending);
}
static void SortItems(IList<TreeViewItem> children, ColumnId columnId, bool ascending = true)
{
if (children == null)
{
return;
}
IList<TreeViewItem> sortedRows;
switch (columnId)
{
case ColumnId.Details:
{
sortedRows = children.Order(x => ((EditorIterationProfilerTreeViewItem)x).Details, ascending).ToList();
break;
}
case ColumnId.Duration:
{
sortedRows = children.Order(x => ((EditorIterationProfilerTreeViewItem)x).Duration, ascending).ToList();
break;
}
default:
{
sortedRows = children.Order(x => ((EditorIterationProfilerTreeViewItem)x).displayName, ascending).ToList();
break;
}
}
children.Clear();
foreach (var r in sortedRows)
{
children.Add(r);
}
foreach (var c in children)
{
SortItems(c.children, columnId, ascending);
}
}
protected override void DoubleClickedItem(int id)
{
if (hasSearch && state.selectedIDs.Count != 0)
{
ClearSearch();
CollapseAll();
FrameItem(id);
}
else
{
SetExpanded(id, !IsExpanded(id));
}
}
internal void ClearSearch()
{
searchString = string.Empty;
}
protected override TreeViewItem BuildRoot()
{
var root = new EditorIterationProfilerTreeViewItem { id = 0, depth = -1, displayName = "Root", Details = null };
var allItems = new List<TreeViewItem>();
var iterationList = EditorIterationProfilerIntegration.Instance.IterationList;
var idCounter = 1;
var iterationCounter = 1;
var eventDataFlagsFilter = EventDataFlags.None;
if (UserCodeOnly)
{
eventDataFlagsFilter |= EventDataFlags.UserCode;
}
if (Flatten)
{
eventDataFlagsFilter |= EventDataFlags.Flatten;
}
for (var i = 0; i < iterationList.IterationEventRoots.Count; ++i)
{
var eventDataList = iterationList.IterationEventRoots[i];
var iterationItem = new EditorIterationProfilerTreeViewItem { id = idCounter++, depth = 0, displayName = string.Empty };
double iterationDuration = 0;
allItems.Add(iterationItem);
foreach (var eventData in eventDataList.Events)
{
if (eventData.ParentIndex < 0)
{
iterationDuration += eventData.Duration;
AddEventDataRecursive(eventData, allItems, ref idCounter, 1, eventDataFlagsFilter);
}
}
iterationItem.displayName = $"Iteration Event {iterationCounter++} ({iterationList.IterationEventKinds[i]})";
iterationItem.Duration = iterationDuration;
}
SetupParentsAndChildrenFromDepths(root, allItems);
return root;
}
static bool ShouldAddTreeViewItem(EventData eventData, EventDataFlags filter)
{
var flags = eventData.Flags;
if (eventData.Kind != IterationEventKind.None)
{
return true;
}
if (filter == EventDataFlags.None)
{
return true;
}
if (filter.HasFlag(EventDataFlags.UserCode) && filter.HasFlag(EventDataFlags.Flatten))
{
if ((flags & filter).HasFlag(EventDataFlags.UserCode))
{
if ((flags & filter).HasFlag(EventDataFlags.Flatten))
{
return false;
}
return true;
}
return false;
}
if ((flags & filter).HasFlag(EventDataFlags.UserCode))
{
return true;
}
if (!(flags & filter).HasFlag(EventDataFlags.Flatten))
{
if (filter.HasFlag(EventDataFlags.Flatten))
{
return true;
}
}
return false;
}
static void AddEventDataRecursive(EventData eventData, List<TreeViewItem> treeViewItems, ref int idCounter, int depth, EventDataFlags eventDataFlagsFilter)
{
if (ShouldAddTreeViewItem(eventData, eventDataFlagsFilter))
{
treeViewItems.Add(new EditorIterationProfilerTreeViewItem
{
id = idCounter++,
depth = depth++,
displayName = eventData.DisplayName,
Details = eventData.Details,
Duration = eventData.Duration
});
}
if (eventData.Children == null)
{
return;
}
foreach (var child in eventData.Children)
{
AddEventDataRecursive(child, treeViewItems, ref idCounter, depth, eventDataFlagsFilter);
}
}
protected override void RowGUI(RowGUIArgs args)
{
var item = (EditorIterationProfilerTreeViewItem)args.item;
for (var i = 0; i < args.GetNumVisibleColumns(); ++i)
{
CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args);
}
}
void CellGUI(Rect cellRect, EditorIterationProfilerTreeViewItem item, int column, ref RowGUIArgs args)
{
args.rowRect = cellRect;
switch (column)
{
case 0:
{
base.RowGUI(args);
break;
}
case 1:
{
if (!string.IsNullOrEmpty(item.Details))
{
DefaultGUI.Label(cellRect, item.Details, args.selected, args.focused);
}
break;
}
case 2:
{
DefaultGUI.LabelRightAligned(cellRect, $"{item.Duration:0.000}", args.selected, args.focused);
break;
}
}
}
public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderState()
{
var columns = new[]
{
new MultiColumnHeaderState.Column
{
headerContent = new GUIContent("Event"),
headerTextAlignment = TextAlignment.Left,
sortingArrowAlignment = TextAlignment.Left,
minWidth = 250,
autoResize = true,
allowToggleVisibility = false
},
new MultiColumnHeaderState.Column
{
headerContent = new GUIContent("Details"),
headerTextAlignment = TextAlignment.Left,
sortingArrowAlignment = TextAlignment.Center,
minWidth = 100,
autoResize = false,
allowToggleVisibility = true
},
new MultiColumnHeaderState.Column
{
headerContent = new GUIContent("Duration (ms)"),
headerTextAlignment = TextAlignment.Left,
sortingArrowAlignment = TextAlignment.Right,
minWidth = 100,
autoResize = false,
allowToggleVisibility = false
}
};
Assert.AreEqual(columns.Length, k_ColumnTypes.Length, L10n.Tr($"Number of columns should match number of {k_ColumnTypes}"));
return new MultiColumnHeaderState(columns);
}
}
static class ExtensionMethods
{
public static IOrderedEnumerable<T> Order<T, TKey>(this IEnumerable<T> source, Func<T, TKey> selector, bool ascending)
{
if (ascending)
{
return source.OrderBy(selector);
}
return source.OrderByDescending(selector);
}
public static IOrderedEnumerable<T> ThenBy<T, TKey>(this IOrderedEnumerable<T> source, Func<T, TKey> selector, bool ascending)
{
if (ascending)
{
return source.ThenBy(selector);
}
else
{
return source.ThenByDescending(selector);
}
}
}
}
================================================
FILE: Editor/EditorIterationProfilerTreeView.cs.meta
================================================
fileFormatVersion: 2
guid: e6651dd15ebe6e1478d78afed8ff3dee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EditorIterationProfilerWindow.cs
================================================
using System;
using System.IO;
using System.Reflection;
using UnityEditor.EditorIterationProfiler.Formatting;
using UnityEditor.IMGUI.Controls;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Assertions;
using ExportStatus = UnityEditor.EditorIterationProfiler.EditorIterationProfilerAnalytics.ExportStatus;
using ExportType = UnityEditor.EditorIterationProfiler.EditorIterationProfilerAnalytics.ExportType;
namespace UnityEditor.EditorIterationProfiler
{
public class EditorIterationProfilerWindow : EditorWindow
{
internal static class Styles
{
public static readonly GUIContent k_EnableProfiler = EditorGUIUtility.TrTextContent("Enable");
public static readonly GUIContent k_ClearProfilerData = EditorGUIUtility.TrTextContent("Clear");
public static readonly GUIContent k_DeepProfile = EditorGUIUtility.TrTextContent("Deep Profile", "Show all managed calls");
public static readonly GUIContent k_UserCode = EditorGUIUtility.TrTextContent("User Code", "Only show user code");
public static readonly GUIContent k_Flatten = EditorGUIUtility.TrTextContent("Flatten", "Flatten markers");
public static readonly GUIContent k_CollapseAll = EditorGUIUtility.TrTextContent("Collapse All", "Collapse all foldouts");
public static readonly GUIContent k_LogConsole = EditorGUIUtility.TrTextContent("Print to Console", "Prints plaintext into the log and console");
public static readonly GUIContent k_Export = EditorGUIUtility.TrTextContent("Export...", "Exports the data captured by the Editor Iteration Profiler");
public static readonly GUIContent k_ExportProfiler = EditorGUIUtility.TrTextContent("Export Profiler Data...", "Exports the selected frame or the last frame in the Profiler");
public const string k_EditorIterationProfilerPrefix = "EIP_";
public const string k_EnableProfilerPref = k_EditorIterationProfilerPrefix + "ProfilingEnabled";
public const string k_EnableDeepProfile = k_EditorIterationProfilerPrefix + "DeepProfilingEnabled";
public const string k_UserCodePref = k_EditorIterationProfilerPrefix + "UserCodeOnly";
public const string k_FlattenPref = k_EditorIterationProfilerPrefix + "Flatten";
public const string k_EventHeaderWidthSizePref = k_EditorIterationProfilerPrefix + "EventHeaderWidthSizePref";
public const string k_DetailsHeaderWidthSizePref = k_EditorIterationProfilerPrefix + "DetailsWidthSizePref";
public const string k_DurationHeaderWidthSizePref = k_EditorIterationProfilerPrefix + "HeaderWidthSizePref";
public const float k_SingleLineHeight =
#if UNITY_2019_3_OR_NEWER
18;
#else
16;
#endif
}
[NonSerialized]
bool m_Initialized;
[SerializeField]
MultiColumnHeaderState m_MultiColumnHeaderState;
[SerializeField]
TreeViewState m_TreeViewState;
EditorIterationProfilerTreeView m_TreeView;
SearchField m_SearchField;
bool isWindowReady = false;
[MenuItem("Window/Analysis/Editor Iteration Profiler/Show Window", priority = 8)]
static void ShowProfilerWindow()
{
var window = GetWindow<EditorIterationProfilerWindow>("Editor Iteration Profiler");
window.minSize = new Vector2(500, 300);
}
void OnEnable()
{
isWindowReady = false;
EditorApplication.delayCall += OnEnableInitialize;
}
void OnEnableInitialize()
{
if (!m_Initialized)
{
InitializeButtonStateFromPrefs();
if (m_TreeViewState == null)
{
m_TreeViewState = new TreeViewState();
}
bool firstInit = m_MultiColumnHeaderState == null;
var headerState = EditorIterationProfilerTreeView.CreateDefaultMultiColumnHeaderState();
if (MultiColumnHeaderState.CanOverwriteSerializedFields(m_MultiColumnHeaderState, headerState))
{
MultiColumnHeaderState.OverwriteSerializedFields(m_MultiColumnHeaderState, headerState);
}
m_MultiColumnHeaderState = headerState;
InitializeHeaderStateFromPrefs(headerState);
var multiColumnHeader = new MultiColumnHeader(headerState);
if (firstInit)
{
multiColumnHeader.ResizeToFit();
}
m_TreeView = new EditorIterationProfilerTreeView(m_TreeViewState, multiColumnHeader);
m_SearchField = new SearchField();
m_SearchField.downOrUpArrowKeyPressed += m_TreeView.SetFocusAndEnsureSelectedItem;
m_Initialized = true;
isWindowReady = true;
}
}
void DrawToolbar()
{
GUILayout.BeginHorizontal(EditorStyles.toolbar);
UnityProfiling.EditorProfilingEnabled = GUILayout.Toggle(UnityProfiling.EditorProfilingEnabled, Styles.k_EnableProfiler, EditorStyles.toolbarButton);
UnityProfiling.SetProfileDeepScripts(GUILayout.Toggle(ProfilerDriver.deepProfiling, Styles.k_DeepProfile, EditorStyles.toolbarButton));
var flatten = GUILayout.Toggle(m_TreeView.Flatten, Styles.k_Flatten, EditorStyles.toolbarButton);
var userCodeOnly = GUILayout.Toggle(m_TreeView.UserCodeOnly, Styles.k_UserCode, EditorStyles.toolbarButton);
GUILayout.Space(5);
if (GUILayout.Button(Styles.k_ClearProfilerData, EditorStyles.toolbarButton))
{
EditorIterationProfilerIntegration.Clear();
}
if (GUILayout.Button(Styles.k_CollapseAll, EditorStyles.toolbarButton))
{
m_TreeView.CollapseAll();
}
if (GUILayout.Button(Styles.k_LogConsole, EditorStyles.toolbarButton))
{
var reporter = EditorIterationProfilerIntegration.Instance.DataReporterProvider.TryGetDataReporter("EditorLogReporter");
reporter.Report(EditorIterationProfilerIntegration.Instance.IterationList);
}
if (EditorGUILayout.DropdownButton(Styles.k_Export, FocusType.Passive, EditorStyles.toolbarPopup))
{
var menu = new GenericMenu();
var exporters = EditorIterationProfilerIntegration.Instance.DataReporterProvider.GetAllReporters<IFileDataReporter>();
foreach (var exporter in exporters)
{
menu.AddItem(new GUIContent(exporter.Name), false, () => ReportExtension(exporter, EditorIterationProfilerIntegration.Instance.IterationList, ExportType.Captured));
}
menu.AddSeparator("");
menu.AddItem(new GUIContent("Export all available formats"), false, () => ReportAllExtensions(EditorIterationProfilerIntegration.Instance.IterationList));
var dropDownRect = EditorGUILayout.GetControlRect();
dropDownRect.x += 500;
dropDownRect.y += 18;
menu.DropDown(dropDownRect);
}
if (EditorGUILayout.DropdownButton(Styles.k_ExportProfiler, FocusType.Passive, EditorStyles.toolbarPopup))
{
var menu = new GenericMenu();
var exporters = EditorIterationProfilerIntegration.Instance.DataReporterProvider.GetAllReporters<IFileDataReporter>();
var assembly = typeof(Editor).Assembly;
var windowType = assembly.GetType("UnityEditor.ProfilerWindow");
var profilerWindow = GetWindow(windowType);
var currentFrameInfo = windowType.GetField("m_CurrentFrame", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.IsNotNull(currentFrameInfo);
int currentFrameIndex = (int)currentFrameInfo.GetValue(profilerWindow);
foreach (var exporter in exporters)
{
menu.AddItem(new GUIContent("Selected Frame/" + exporter.Name), false, () => ReportSelectedFrame(exporter, currentFrameIndex));
}
menu.AddSeparator("");
foreach (var exporter in exporters)
{
menu.AddItem(new GUIContent("Multiple Frames/" + exporter.Name), false, () =>
{
var window = GetWindow<ProfilerMultiFrameSelector>();
window.Initialize(exporter);
});
}
var dropDownRect = EditorGUILayout.GetControlRect();
dropDownRect.x += 600;
dropDownRect.y += 18;
menu.DropDown(dropDownRect);
}
GUILayout.Space(5);
GUILayout.FlexibleSpace();
if (m_TreeView.UserCodeOnly != userCodeOnly)
{
EditorIterationProfilerAnalytics.SendInteractionEvent(UnityProfiling.EditorProfilingEnabled, EditorApplication.isPlaying, ProfilerDriver.deepProfiling, EditorIterationProfilerIntegration.Instance.Settings.Flatten, EditorIterationProfilerIntegration.Instance.Settings.UserCode);
m_TreeView.UserCodeOnly = userCodeOnly;
EditorPrefs.SetBool(Styles.k_UserCodePref, m_TreeView.UserCodeOnly);
m_TreeView.Reload();
}
if (m_TreeView.Flatten != flatten)
{
EditorIterationProfilerAnalytics.SendInteractionEvent(UnityProfiling.EditorProfilingEnabled, EditorApplication.isPlaying, ProfilerDriver.deepProfiling, EditorIterationProfilerIntegration.Instance.Settings.Flatten, EditorIterationProfilerIntegration.Instance.Settings.UserCode);
m_TreeView.Flatten = flatten;
EditorPrefs.SetBool(Styles.k_FlattenPref, m_TreeView.Flatten);
m_TreeView.Reload();
}
DrawSearchBar();
GUILayout.EndHorizontal();
}
public static void ReportMultipleFrames(IFileDataReporter reporter, int beginRange, int endRange, string guid)
{
var exportType = ExportType.Multi;
if (beginRange == -1)
{
ReportSelectedFrame(reporter, beginRange, exportType, guid);
return;
}
EditorIterationProfilerAnalytics.SendExportEvent(reporter.Name, exportType.ToString(), ExportStatus.Started.ToString(), guid);
var path = EditorUtility.SaveFolderPanel($"Export frames to folder", "", reporter.Extension);
for (int i = beginRange - 1; i < endRange; ++i)
{
var list = new IterationList();
var hfdv = UnityProfiling.GetFrame(i, 0);
if (!hfdv.valid)
{
hfdv = UnityProfiling.GetFrame(-1, 0);
if (!hfdv.valid)
{
EditorIterationProfilerAnalytics.SendExportEvent(reporter.Name, exportType.ToString(), ExportStatus.Error.ToString(), guid);
Debug.LogError($"There was an issue getting the frame {i}");
return;
}
}
list.NewIteration(IterationEventKind.None);
Assert.IsNotNull(list.LastIterationEventRoot);
list.LastIterationEventRoot.StartEvent(IterationEventKind.None);
ProfilerDataCollector.ReadProfilingData(list.LastIterationEventRoot, list.LastIterationEventRoot.FindLastEvent(IterationEventKind.None), hfdv, hfdv.GetRootItemID(), EventDataFlags.None, false);
var lastEvent = list.LastIterationEventRoot.FindLastEvent(IterationEventKind.None);
Assert.IsNotNull(lastEvent);
lastEvent.SetStartFinishTimeFromChildren();
lastEvent.Identifier = $"Data (Frame {i + 1})";
var filename = "EditorIterationData_" + $"Frame{i + 1}_" + $"{DateTime.Now.ToString("MMddyyyy_HHmmss")}" + $".{reporter.Extension}";
if (path.Length != 0)
{
reporter.Report(list, Path.Combine(path, filename));
}
}
if (path.Length != 0)
{
EditorIterationProfilerAnalytics.SendExportEvent(reporter.Name, exportType.ToString(), ExportStatus.Finished.ToString(), guid);
}
}
static void ReportSelectedFrame(IFileDataReporter reporter, int currentFrameIndex, ExportType exportType = ExportType.Selected, string guid = "")
{
if (string.IsNullOrEmpty(guid))
{
guid = Guid.NewGuid().ToString();
EditorIterationProfilerAnalytics.SendExportEvent(reporter.Name, exportType.ToString(), ExportStatus.Started.ToString(), guid);
}
var list = new IterationList();
var hfdv = UnityProfiling.GetFrame(currentFrameIndex, 0);
if (!hfdv.valid)
{
hfdv = UnityProfiling.GetFrame(-1, 0);
if (!hfdv.valid)
{
EditorIterationProfilerAnalytics.SendExportEvent(reporter.Name, exportType.ToString(), ExportStatus.Error.ToString(), guid);
Debug.LogError($"There was an issue getting the frame {currentFrameIndex}");
return;
}
}
list.NewIteration(IterationEventKind.None);
Assert.IsNotNull(list.LastIterationEventRoot);
list.LastIterationEventRoot.StartEvent(IterationEventKind.None);
ProfilerDataCollector.ReadProfilingData(list.LastIterationEventRoot, list.LastIterationEventRoot.FindLastEvent(IterationEventKind.None), hfdv, hfdv.GetRootItemID(), EventDataFlags.None, false);
var lastEvent = list.LastIterationEventRoot.FindLastEvent(IterationEventKind.None);
Assert.IsNotNull(lastEvent);
lastEvent.SetStartFinishTimeFromChildren();
lastEvent.Identifier = $"Data (Frame {currentFrameIndex + 1})";
ReportExtension(reporter, list, exportType, guid);
}
static void ReportAllExtensions(IIterationList iterationList)
{
var guid = Guid.NewGuid().ToString();
var path = EditorUtility.SaveFolderPanel($"Export frames to folder", "", "");
var extensions = EditorIterationProfilerIntegration.Instance.DataReporterProvider.GetAllReporters<IFileDataReporter>();
foreach (var extension in extensions)
{
ReportExtension(extension, iterationList, ExportType.CapturedAll, guid, path);
}
}
static void ReportExtension(IFileDataReporter fileReporterType, IIterationList iterationList, ExportType exportType, string guid = "", string folderPath = "")
{
if (string.IsNullOrEmpty(guid))
{
guid = Guid.NewGuid().ToString();
}
if(ExportType.Selected != exportType)
{
EditorIterationProfilerAnalytics.SendExportEvent(fileReporterType.Name, exportType.ToString(), ExportStatus.Started.ToString(), guid);
}
var reporter = EditorIterationProfilerIntegration.Instance.DataReporterProvider.TryGetReporter<IFileDataReporter>(fileReporterType.GetType());
if (reporter == null)
{
return;
}
var filename = "EditorIterationData_" + $"{reporter.Name.Replace(" ", "")}_" + $"{DateTime.Now.ToString("MMddyyyy_HHmmss")}" + $".{reporter.Extension}";
string path;
if (string.IsNullOrEmpty(folderPath))
{
path = EditorUtility.SaveFilePanel($"Export {reporter.Extension}", "", filename, reporter.Extension);
}
else
{
path = Path.Combine(folderPath, filename);
}
if (path.Length != 0)
{
reporter.Report(iterationList, path);
EditorIterationProfilerAnalytics.SendExportEvent(reporter.Name, exportType.ToString(), ExportStatus.Finished.ToString(), guid);
}
}
void DrawSearchBar()
{
var rect = GUILayoutUtility.GetRect(50f, 300f, Styles.k_SingleLineHeight, Styles.k_SingleLineHeight, EditorStyles.toolbarSearchField);
var searchLength = m_TreeView.searchString?.Length ?? 0;
m_TreeView.searchString = m_SearchField.OnToolbarGUI(rect, m_TreeView.searchString);
if (searchLength > 0 && !m_TreeView.hasSearch)
{
m_TreeView.CollapseAll();
try
{
m_TreeView.FrameItem(m_TreeView.state.lastClickedID);
}
catch (ArgumentException)
{
m_TreeView.state.lastClickedID = -1;
}
}
}
void DrawTreeView()
{
var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
m_TreeView.OnGUI(rect);
}
void OnLostFocus()
{
EditorIterationProfilerAnalytics.SendInteractionEvent(UnityProfiling.EditorProfilingEnabled, EditorApplication.isPlaying, ProfilerDriver.deepProfiling, EditorIterationProfilerIntegration.Instance.Settings.Flatten, EditorIterationProfilerIntegration.Instance.Settings.UserCode);
}
void OnGUI()
{
if(!isWindowReady)
{
return;
}
DrawToolbar();
DrawTreeView();
UpdatePrefs();
}
static void InitializeButtonStateFromPrefs()
{
if (!EditorPrefs.HasKey(Styles.k_EnableProfilerPref))
{
EditorPrefs.SetBool(Styles.k_EnableProfilerPref, false);
}
if (!EditorPrefs.HasKey(Styles.k_UserCodePref))
{
EditorPrefs.SetBool(Styles.k_UserCodePref, false);
}
if (!EditorPrefs.HasKey(Styles.k_FlattenPref))
{
EditorPrefs.SetBool(Styles.k_FlattenPref, false);
}
if (!EditorPrefs.HasKey(Styles.k_EnableDeepProfile))
{
EditorPrefs.SetBool(Styles.k_EnableDeepProfile, false);
}
UnityProfiling.EditorProfilingEnabled = EditorPrefs.GetBool(Styles.k_EnableProfilerPref);
UnityProfiling.SetProfileDeepScripts(EditorPrefs.GetBool(Styles.k_EnableDeepProfile));
}
static void InitializeHeaderStateFromPrefs(MultiColumnHeaderState state)
{
int columnIndex = 0;
if (!EditorPrefs.HasKey(Styles.k_EventHeaderWidthSizePref))
{
EditorPrefs.SetFloat(Styles.k_EventHeaderWidthSizePref, state.columns[columnIndex++].minWidth);
}
if (!EditorPrefs.HasKey(Styles.k_DetailsHeaderWidthSizePref))
{
EditorPrefs.SetFloat(Styles.k_DetailsHeaderWidthSizePref, state.columns[columnIndex++].minWidth);
}
if (!EditorPrefs.HasKey(Styles.k_DurationHeaderWidthSizePref))
{
EditorPrefs.SetFloat(Styles.k_DurationHeaderWidthSizePref, state.columns[columnIndex].minWidth);
}
columnIndex = 0;
state.columns[columnIndex++].width = EditorPrefs.GetFloat(Styles.k_EventHeaderWidthSizePref);
state.columns[columnIndex++].width = EditorPrefs.GetFloat(Styles.k_DetailsHeaderWidthSizePref);
state.columns[columnIndex].width = EditorPrefs.GetFloat(Styles.k_DurationHeaderWidthSizePref);
}
void UpdatePrefs()
{
EditorPrefs.SetFloat(Styles.k_EventHeaderWidthSizePref, m_MultiColumnHeaderState.columns[0].width);
EditorPrefs.SetFloat(Styles.k_DetailsHeaderWidthSizePref, m_MultiColumnHeaderState.columns[1].width);
EditorPrefs.SetFloat(Styles.k_DurationHeaderWidthSizePref, m_MultiColumnHeaderState.columns[2].width);
EditorPrefs.SetBool(Styles.k_EnableProfilerPref, UnityProfiling.EditorProfilingEnabled);
}
[MenuItem("Window/Analysis/Editor Iteration Profiler/Clear Editor Preferences", priority = 20)]
static void DeleteAllEIPPrefKeys()
{
if (EditorUtility.DisplayDialog("Delete EIP Editor Preferences", "Delete EIP Editor Preferences?", "Yes", "No"))
{
EditorPrefs.DeleteKey(Styles.k_DurationHeaderWidthSizePref);
EditorPrefs.DeleteKey(Styles.k_DetailsHeaderWidthSizePref);
EditorPrefs.DeleteKey(Styles.k_EventHeaderWidthSizePref);
EditorPrefs.DeleteKey(Styles.k_UserCodePref);
EditorPrefs.DeleteKey(Styles.k_EnableDeepProfile);
EditorPrefs.DeleteKey(Styles.k_EnableProfilerPref);
Debug.Log("EIP Editor Preferences deleted");
}
}
}
class ProfilerMultiFrameSelector : EditorWindow
{
public static readonly GUIContent k_RangeBeginning = EditorGUIUtility.TrTextContent("Range Beginning", "Range beginning, value is inclusive.");
public static readonly GUIContent k_RangeEnd = EditorGUIUtility.TrTextContent("Range End", "Range end, value is inclusive.");
public static readonly GUIContent k_WindowTitle = EditorGUIUtility.TrTextContent("Multi-Frame Exporter");
IFileDataReporter m_Exporter;
int m_FirstRange = -1;
int m_SecondRange = -1;
string m_EventGuid;
static void OpenWindow()
{
GetWindow<ProfilerMultiFrameSelector>();
}
public void Initialize(IFileDataReporter exporter)
{
m_Exporter = exporter;
m_EventGuid = Guid.NewGuid().ToString();
EditorIterationProfilerAnalytics.SendExportEvent(exporter.Name, ExportType.MultiWindow.ToString(), ExportStatus.Started.ToString(), m_EventGuid);
}
public void OnDestroy()
{
EditorIterationProfilerAnalytics.SendExportEvent(m_Exporter.Name, ExportType.MultiWindow.ToString(), ExportStatus.Finished.ToString(), m_EventGuid);
}
void OnEnable()
{
maxSize = new Vector2(300, 125);
minSize = new Vector2(300, 125);
titleContent = k_WindowTitle;
ShowUtility();
}
void OnGUI()
{
m_FirstRange = EditorGUILayout.IntField(k_RangeBeginning, m_FirstRange);
m_SecondRange = EditorGUILayout.IntField(k_RangeEnd, m_SecondRange);
EditorGUILayout.HelpBox("Integers only. The limits are INCLUSIVE. If frame does not exist it won't be exported. -1 is the newest frame, however you can't do -1 and 15, for example; only -1 and -1.", MessageType.Info);
if (m_FirstRange > m_SecondRange)
{
int x = m_FirstRange;
m_FirstRange = m_SecondRange;
m_SecondRange = x;
}
bool areValid = (m_FirstRange == m_SecondRange && m_FirstRange == -1 || m_FirstRange >= 0 && m_SecondRange >= 0);
EditorGUI.BeginDisabledGroup(!areValid);
if (GUILayout.Button("Export"))
{
Debug.Log($"Exporting Frames [{m_FirstRange},{m_SecondRange}] ({Mathf.Abs(m_SecondRange) - Mathf.Abs(m_FirstRange) + 1} frames)");
EditorIterationProfilerWindow.ReportMultipleFrames(m_Exporter, m_FirstRange, m_SecondRange, m_EventGuid);
Close();
}
EditorGUI.EndDisabledGroup();
}
}
}
================================================
FILE: Editor/EditorIterationProfilerWindow.cs.meta
================================================
fileFormatVersion: 2
guid: 906f7aecdbdac3e4ba9518ba48388df9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/EventData.cs
================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler
{
[Flags]
public enum EventDataFlags
{
None = 0,
UserCode = 1 << 0,
Flatten = 1 << 1,
}
[Serializable]
public class EventData
{
[field: NonSerialized]
public List<EventData> Children { get; set; } = new List<EventData>();
public int Index { get; }
public int ParentIndex { get; set; }
public string Identifier { get; set; }
public double StartTime { get; set; }
public double FinishTime { get; set; }
public EventDataFlags Flags { get; set; }
public IterationEventKind Kind { get; }
[SerializeField]
string m_Metadata;
public string Details => m_Metadata;
public string DisplayName
{
get
{
if (Kind == IterationEventKind.None)
{
return $"{Identifier}";
}
string kindString = Kind.ToString();
if (kindString == Identifier)
{
return kindString;
}
return $"{kindString}: {Identifier}";
}
}
public double Duration => FinishTime - StartTime;
static double CurrentTime
{
get
{
long timeStamp = Stopwatch.GetTimestamp() / TimeSpan.TicksPerMillisecond;
return timeStamp;
}
}
public EventData(IterationEventKind kind, string identifier, string metadata, int index)
{
Kind = kind;
Flags = EventDataFlags.None;
Identifier = identifier;
m_Metadata = metadata;
Index = index;
ParentIndex = -1;
StartTime = -1.0f;
FinishTime = -1.0f;
}
public EventData(string identifier, string metadata, int index, double startTime, double finishTime, EventDataFlags flags)
{
Kind = IterationEventKind.None;
Identifier = identifier;
m_Metadata = metadata;
Index = index;
ParentIndex = -1;
StartTime = startTime;
FinishTime = finishTime;
Flags = flags;
}
public void SetStartTime()
{
StartTime = CurrentTime;
FinishTime = StartTime;
}
public void Finish()
{
if (StartTime > 0.0f)
{
FinishTime = CurrentTime;
}
}
public void SetStartFinishTimeFromChildren()
{
if (Children.Count == 0)
{
return;
}
StartTime = Children.First().StartTime;
FinishTime = Children.First().FinishTime;
foreach (var child in Children)
{
StartTime = Math.Min(child.StartTime, StartTime);
FinishTime = Math.Max(child.FinishTime, FinishTime);
}
}
public void PostProcess(bool flatten = false)
{
if (Children.Count == 0)
{
return;
}
if (flatten && Children.Count == 1)
{
Flags |= EventDataFlags.Flatten;
}
foreach (var child in Children)
{
child.PostProcess(Children.Count == 1);
}
}
}
}
================================================
FILE: Editor/EventData.cs.meta
================================================
fileFormatVersion: 2
guid: 7ffe19a10dc4360459985d005f84ceab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Aggregator.cs
================================================
using System;
using System.Text;
using System.Text.RegularExpressions;
using static System.Double;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public class Aggregator
{
public string Name { get; private set; }
public double Time { get; private set; }
public double TotalTime { get; private set; }
public Regex Pattern { get; private set; }
public int Depth { get; private set; }
public int Calls { get; private set; }
public bool IsRoot => !string.IsNullOrEmpty(Name) && m_Sb.Length != 0;
public double Percentage => (Math.Abs(TotalTime) < Epsilon || Math.Abs(Time) < Epsilon) ? 0 : Time / TotalTime * 100;
StringBuilder m_Sb;
public Aggregator(int depth, string name, Regex pattern)
{
m_Sb = new StringBuilder();
Time = 0;
TotalTime = 0;
Calls = 0;
Name = name;
Depth = depth;
Pattern = pattern;
}
public void Aggregate(string s, bool isCall = false)
{
m_Sb.Append(s);
if (isCall)
{
++Calls;
}
}
public void Aggregate(double time)
{
++Calls;
Time += time;
}
public void Aggregate(string s, double time)
{
Aggregate(s);
Aggregate(time);
}
public void Reset()
{
Calls = 0;
m_Sb.Clear();
Time = 0;
TotalTime = 0;
}
public void Reset(double totalTime)
{
Calls = 0;
m_Sb.Clear();
Time = 0;
TotalTime = totalTime;
}
public override string ToString()
{
return m_Sb.ToString();
}
}
public class HTMLAggregator : Aggregator
{
public string Style { get; private set;}
public HTMLAggregator(int depth, string name, Regex pattern, string style) : base(depth, name, pattern)
{
Style = style;
}
}
}
================================================
FILE: Editor/Formatters/Aggregator.cs.meta
================================================
fileFormatVersion: 2
guid: 25551dbb66e6c084ab84c7a8e6cfc2e2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/DataReporterProvider.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.EditorIterationProfiler.Formatting;
using UnityEngine.Assertions;
namespace UnityEditor.EditorIterationProfiler
{
public interface IDataReporterProvider
{
IList<T> GetAllReporters<T>() where T : IDataReporter;
T TryGetReporter<T>(Type type) where T : IDataReporter;
bool IsFileExtensionSupported(string extension);
IDataReporter TryGetDataReporter(string typeName);
IFileDataReporter TryGetDataFileReporter(string typeName);
}
public class DataReporterProvider : IDataReporterProvider
{
HashSet<IDataReporter> m_DataReporters;
HashSet<IFileDataReporter> m_DataFileReporters;
public DataReporterProvider()
{
InitializeDataFileReporters();
InitializeDataReporters();
}
void InitializeDataFileReporters()
{
m_DataFileReporters = new HashSet<IFileDataReporter>();
foreach (var rep in TypeCache.GetTypesDerivedFrom(typeof(IFileDataReporter)))
{
if (rep.GetConstructors().Length > 0)
{
var instance = (IFileDataReporter)Activator.CreateInstance(rep);
var processedExtension = SanitizeExtension(instance.Extension);
if (processedExtension != instance.Extension)
{
throw new ArgumentException($"Extension must be lowercase characters only ({rep})");
}
else
{
m_DataFileReporters.Add(instance);
}
}
}
}
void InitializeDataReporters()
{
m_DataReporters = new HashSet<IDataReporter>();
foreach (var rep in TypeCache.GetTypesDerivedFrom(typeof(IDataReporter)))
{
if (rep.GetConstructors().Length > 0)
{
var instance = (IDataReporter)Activator.CreateInstance(rep);
if (!(instance is FileReporter))
{
m_DataReporters.Add(instance);
}
}
}
}
public IList<T> GetAllReporters<T>() where T : IDataReporter
{
if (typeof(T) == typeof(IDataReporter))
{
return (IList<T>)m_DataReporters.ToList();
}
if (typeof(T) == typeof(IFileDataReporter))
{
return (IList<T>)m_DataFileReporters.ToList();
}
return default;
}
public T TryGetReporter<T>(Type type) where T : IDataReporter
{
if (typeof(T) == typeof(IDataReporter))
{
return (T)m_DataReporters.FirstOrDefault(x => x.GetType() == type);
}
if (typeof(T) == typeof(IFileDataReporter))
{
return (T)m_DataFileReporters.FirstOrDefault(x => x.GetType() == type);
}
return default;
}
public IDataReporter TryGetDataReporter(string typeName)
{
return m_DataReporters.FirstOrDefault(reporter => reporter.GetType().Name == typeName);
}
public IFileDataReporter TryGetDataFileReporter(string typeName)
{
return m_DataFileReporters.FirstOrDefault(reporter => reporter.GetType().Name == typeName);
}
public bool IsFileExtensionSupported(string extension)
{
return m_DataFileReporters.Any(reporter => reporter.Extension == SanitizeExtension(extension));
}
static string SanitizeExtension(string extension)
{
Assert.IsNotNull(extension, "Extension cannot be null");
if (extension.StartsWith("."))
{
return extension.Substring(1);
}
extension = extension.ToLower();
return extension;
}
}
}
================================================
FILE: Editor/Formatters/DataReporterProvider.cs.meta
================================================
fileFormatVersion: 2
guid: ff2c9a40c83aa784bb9b3ff6047ee281
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/DataReporters.cs
================================================
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public interface IDataReporter
{
string GetFormatString(in IIterationList iterationList);
void Report(in IIterationList iterationList, string path = null);
}
public interface IFileDataReporter : IDataReporter
{
string Extension { get; }
string Name { get; }
new void Report(in IIterationList iterationList, string path);
}
}
================================================
FILE: Editor/Formatters/DataReporters.cs.meta
================================================
fileFormatVersion: 2
guid: 81edb0b5aa41ccd48ad73a8a21e67758
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/FileReporter.cs
================================================
using System;
using System.IO;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public abstract class FileReporter : Formatter, IFileDataReporter
{
string m_Extension = null;
public virtual string Extension => m_Extension;
string m_Name = null;
public virtual string Name => m_Name;
public virtual void Report(in IIterationList iterationList, string path)
{
ReportToFile(GetFormatString(iterationList), path);
}
protected virtual void ReportToFile(string message, string path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path), "Path cannot be null");
}
File.WriteAllText(path, message);
Debug.Log($"\"{path}\" exported!");
}
public abstract override string ToString();
}
}
================================================
FILE: Editor/Formatters/FileReporter.cs.meta
================================================
fileFormatVersion: 2
guid: 9d728ac882039e643be468b5db8f65b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Formatter.cs
================================================
using System;
using System.Text;
using static System.FormattableString;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public abstract class Formatter
{
public virtual string GetFormatString(in IIterationList iterationList)
{
var finalStringBuilder = GetPrefixStringBuilder(iterationList).Append(GetMainStringBuilder(iterationList).Append(GetPostfixStringBuilder(iterationList)));
return finalStringBuilder.ToString();
}
protected virtual StringBuilder GetPrefixStringBuilder(in IIterationList iterationList = null)
{
return new StringBuilder();
}
protected virtual StringBuilder GetMainStringBuilder(in IIterationList iterationList)
{
var sb = new StringBuilder();
if (iterationList.IterationEventRoots.Count > 0)
{
RecursiveIterationList(iterationList, ref sb);
}
return sb;
}
protected virtual StringBuilder GetPostfixStringBuilder(in IIterationList iterationList = null)
{
return new StringBuilder();
}
protected virtual void RecursiveIterationList(in IIterationList iterationList, ref StringBuilder sb, params object[] parameters)
{
if (iterationList.IterationEventRoots.Count == 0)
{
return;
}
for (int i = 0; i < iterationList.IterationEventRoots.Count; ++i)
{
RecursiveIterationEventRoot(iterationList.IterationEventRoots[i], ref sb, 1, parameters);
}
}
protected virtual void RecursiveIterationEventRoot(in IterationEventRoot iterationEventRoot, ref StringBuilder sb, params object[] parameters)
{
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0)
{
RecursiveEventData(ed, iterationEventRoot, ref sb, parameters);
}
}
}
protected virtual void RecursiveEventData(in EventData ed, in IterationEventRoot iterationEventRoot, ref StringBuilder sb, params object[] parameters)
{
RecursiveEventDataWalker(in ed, in iterationEventRoot, ref sb, parameters);
}
protected virtual void RecursiveEventDataWalker(in EventData ed, in IterationEventRoot iterationEventRoot, ref StringBuilder sb, params object[] parameters)
{
if (ed.Children == null || ed.Children.Count == 0)
{
return;
}
foreach (var child in ed.Children)
{
var newParameters = new object[parameters.Length];
Array.Copy(parameters, newParameters, parameters.Length);
newParameters[0] = (int)newParameters[0] + 1;
RecursiveEventData(child, iterationEventRoot, ref sb, newParameters);
}
}
public static string ToTimeString(double time)
{
return Invariant($"{time:0.000} ms");
}
public static string ToPercentageString(double percentage)
{
return Invariant($"{percentage:0.00}%");
}
}
}
================================================
FILE: Editor/Formatters/Formatter.cs.meta
================================================
fileFormatVersion: 2
guid: ac320eeadb74a314986b94329a9f324b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/IndentationProvider.cs
================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public static class IndentationProvider
{
static Dictionary<int, string> m_Cache = new Dictionary<int, string>(32);
const char k_IndentationChar = '\t';
public static string Get(int count)
{
if (count < 1)
{
return string.Empty;
}
if (!m_Cache.ContainsKey(count))
{
m_Cache.Add(count, new string(k_IndentationChar, count));
}
return m_Cache[count];
}
}
}
================================================
FILE: Editor/Formatters/IndentationProvider.cs.meta
================================================
fileFormatVersion: 2
guid: 3b0423ed7f3314147a6125b4bca1b837
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/CSVReporter.cs
================================================
using System.Text;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
sealed class CSVReporter : FileReporter
{
string m_Extension = "csv";
public override string Extension => m_Extension;
string m_Name = "CSV";
public override string Name => m_Name;
protected override StringBuilder GetPrefixStringBuilder(in IIterationList iterationList = null)
{
var sb = new StringBuilder();
sb.AppendLine($"{EditorIterationProfilerIntegration.Instance.Settings}");
sb.AppendLine();
return sb;
}
protected override void RecursiveIterationList(in IIterationList iterationList, ref StringBuilder sb, params object[] parameters)
{
sb.AppendLine($"Iteration ID,NodeType,Name,Details,Duration (ms)");
for (int i = 0; i < iterationList.IterationEventRoots.Count; ++i)
{
RecursiveIterationEventRoot(iterationList.IterationEventRoots[i], ref sb, 1);
}
}
protected override void RecursiveEventData(in EventData ed, in IterationEventRoot parent, ref StringBuilder sb, params object[] parameters)
{
if (ed.Children.Count == 0)
{
sb.AppendLine($"{parent.IterationIndex + 1} ({parent.IterationEventKind}), Leaf, {ed.Identifier}, {ed.Details}, {ed.Duration:0.000}");
}
else
{
sb.AppendLine($"{parent.IterationIndex + 1} ({parent.IterationEventKind}), Parent, {ed.Identifier}, {ed.Details}, {ed.Duration:0.000}");
}
RecursiveEventDataWalker(in ed, in parent, ref sb, parameters);
}
public override string ToString()
{
return GetType().Name;
}
}
}
================================================
FILE: Editor/Formatters/Reporters/CSVReporter.cs.meta
================================================
fileFormatVersion: 2
guid: 6b8bb4034b7400549b745b3ae7c02f4c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/ChromeTracingReporter.cs
================================================
using System;
using System.Text;
using static System.FormattableString;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
sealed class ChromeTracingReporter : FileReporter
{
string m_Extension = "json";
public override string Extension => m_Extension;
string m_Name = "JSON for Chrometrace";
public override string Name => m_Name;
double m_ParentTotalDuration;
protected override StringBuilder GetPrefixStringBuilder(in IIterationList iterationList = null)
{
var sb = new StringBuilder(32);
sb.AppendLine("{");
sb.AppendLine("\"otherData\": {");
sb.AppendLine($"\"Readme\": \"Data serialized for use with Chrome Tracing. Load this file into chrome://tracing/ \",");
sb.AppendLine($"\"Data\": \"{EditorIterationProfilerIntegration.Instance.Settings.ToString().Replace(Environment.NewLine, "; ")}\"");
sb.AppendLine("},");
sb.AppendLine("\"traceEvents\": [");
return sb;
}
protected override StringBuilder GetMainStringBuilder(in IIterationList iterationList)
{
var sb = new StringBuilder();
if (iterationList.IterationEventRoots.Count > 0)
{
RecursiveIterationList(iterationList, ref sb);
// Remove the last comma
for (int i = sb.Length - 1; i > 0; --i)
{
if (sb[i] == ',')
{
sb.Remove(i, 1);
break;
}
}
}
return sb;
}
protected override StringBuilder GetPostfixStringBuilder(in IIterationList iterationList = null)
{
var sb = new StringBuilder(4);
sb.AppendLine("]");
sb.AppendLine("}");
return sb;
}
protected override void RecursiveIterationEventRoot(in IterationEventRoot iterationEventRoot, ref StringBuilder sb, params object[] parameters)
{
double totalDuration = 0;
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0 && ed.Duration > 0)
{
totalDuration += ed.Duration;
}
}
m_ParentTotalDuration = totalDuration;
sb.AppendLine(MetadataEvent("process_name", (iterationEventRoot.IterationIndex + 1).ToString(), "1", $"Iteration {iterationEventRoot.IterationIndex + 1} ({iterationEventRoot.IterationEventKind.ToString()}) ({totalDuration:0.000}ms) "));
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0)
{
RecursiveEventData(ed, iterationEventRoot, ref sb, ed.StartTime, parameters);
}
}
}
void RecursiveEventData(in EventData ed, in IterationEventRoot iterationEventRoot, ref StringBuilder sb, double parentStartTime, params object[] parameters)
{
if (ed.Duration > float.Epsilon)
{
sb.AppendLine(DurationEvent(ed.Identifier, (iterationEventRoot.IterationIndex + 1).ToString(), "1", iterationEventRoot.IterationEventKind.ToString(), ed.StartTime - parentStartTime, ed.Duration));
}
RecursiveEventDataWalker(in ed, in iterationEventRoot, ref sb, parentStartTime, parameters);
}
void RecursiveEventDataWalker(in EventData ed, in IterationEventRoot iterationEventRoot, ref StringBuilder sb, double parentStartTime, params object[] parameters)
{
if (ed.Children == null || ed.Children.Count == 0)
{
return;
}
foreach (var child in ed.Children)
{
var newParameters = new object[parameters.Length];
Array.Copy(parameters, newParameters, parameters.Length);
newParameters[0] = (int)newParameters[0] + 1;
RecursiveEventData(child, iterationEventRoot, ref sb, parentStartTime, newParameters);
}
}
string DurationEvent(string identifier, string pid, string tid, string category, double startTime, double duration)
{
return Invariant($"{{ \"pid\": {pid}, \"tid\": {tid}, \"ph\": \"X\", \"name\": \"{identifier}\", \"cat\": \"{category}\", \"ts\": {startTime * 1000.0:0.000}, \"dur\": {duration * 1000}, \"args\": {{ \"Duration (ms)\": {duration:0.000}, \"Start Time (ms)\": {startTime:0.000}, \"Percentage of total\": {(duration / m_ParentTotalDuration * 100.0):0.000} }} }},");
}
static string MetadataEvent(string identifier, string pid, string tid, string name)
{
return $"{{ \"pid\": {pid}, \"tid\": {tid}, \"ph\": \"M\", \"name\": \"{identifier}\", \"args\": {{ \"name\": \"{name}\" }} }},";
}
public override string ToString()
{
return GetType().Name;
}
}
}
================================================
FILE: Editor/Formatters/Reporters/ChromeTracingReporter.cs.meta
================================================
fileFormatVersion: 2
guid: 72b0e40bb4a14f3478fcab6254a33ddf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/EditorLogReporter.cs
================================================
using System.Text;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public class EditorLogReporter : Formatter, IDataReporter
{
protected override StringBuilder GetPrefixStringBuilder(in IIterationList iterationList = null)
{
var sb = new StringBuilder();
sb.AppendLine($"{EditorIterationProfilerIntegration.Instance.Settings}");
sb.AppendLine();
return sb;
}
protected override void RecursiveIterationEventRoot(in IterationEventRoot iterationEventRoot, ref StringBuilder sb, params object[] parameters)
{
double totalDuration = 0;
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0 && ed.Duration > 0)
{
totalDuration += ed.Duration;
}
}
sb.AppendLine($"Iteration {iterationEventRoot.IterationIndex + 1} ({iterationEventRoot.IterationEventKind}) [{totalDuration:0.000} ms]");
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0)
{
RecursiveEventData(ed, iterationEventRoot, ref sb, parameters);
}
}
}
protected override void RecursiveEventData(in EventData ed, in IterationEventRoot parent, ref StringBuilder sb, params object[] parameters)
{
var indentation = new string('\t', (int)parameters[0]);
sb.AppendLine($"{indentation}{ed.Identifier} ({ed.Duration:0.000} ms; {ed.Details})");
RecursiveEventDataWalker(in ed, in parent, ref sb, parameters);
}
public void Report(in IIterationList iterationList, string path = null)
{
var message = GetFormatString(iterationList);
Debug.Log(message);
}
}
}
================================================
FILE: Editor/Formatters/Reporters/EditorLogReporter.cs.meta
================================================
fileFormatVersion: 2
guid: 5699fdd33406e234598169fc247e67e6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/HTMLPerfReport.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor.EditorIterationProfiler.Formatting;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler
{
public class HTMLPerfReporter : FileReporter
{
string m_Extension = "html";
public override string Extension => m_Extension;
string m_Name = "HTML Performance Report";
public override string Name => m_Name;
// [0-100] percentage. Determines when the children of the current node will stop being logged. If the Parent is under this percentage, only the direct children of it will be printed. After that it stops.
const double k_PrunePercentage = 1;
// [0-100] percentage. Determines what is considered as a divergence in times. This is used to 'flatten' the structure. 1 will basically turn it 'off'.
const double k_DivergenceFactor = 75;
IList<HTMLAggregator> m_Aggregators = new List<HTMLAggregator>();
double m_ParentTotalDuration;
public HTMLPerfReporter()
{
m_Aggregators.Add(new HTMLAggregator(1, "Garbage Collector", new Regex(@"GC\.C"), "color:#F00"));
m_Aggregators.Add(new HTMLAggregator(1, "Mono.JIT", new Regex("Mono.JIT"), "color:#FA1"));
m_Aggregators.Add(new HTMLAggregator(1, "[MISSING MARKER TIME]", new Regex("MISSING MARKER TIME"), "color:#B54"));
m_Aggregators.Add(new HTMLAggregator(1, "EIP Time", new Regex(@"EditorIterationProfiler"), "color:#3A7"));
m_Aggregators.Add(new HTMLAggregator(1, "Object Stuff", new Regex(@"Object\."), "color:#1C7"));
m_Aggregators.Add(new HTMLAggregator(1, "OnEnable & Awake Stuff", new Regex(@"\.Awake|\.OnEnable"), "color:#17C"));
m_Aggregators.Add(new HTMLAggregator(1, "UnityEditor Stuff", new Regex(@"UnityEditor\."), "color:#52F"));
m_Aggregators.Add(new HTMLAggregator(1, "UnityEngine Stuff", new Regex(@"UnityEngine\."), "color:#81B"));
m_Aggregators.Add(new HTMLAggregator(1, "GUI Stuff", new Regex(@"GUI"), "color:#C0F"));
}
public override string GetFormatString(in IIterationList iterationList)
{
var finalStringBuilder = GetPrefixStringBuilder(iterationList).Append(GetMainStringBuilder(iterationList).Append(GetPostfixStringBuilder(iterationList)));
return finalStringBuilder.ToString();
}
protected override StringBuilder GetPrefixStringBuilder(in IIterationList iterationList = null)
{
var sb = new StringBuilder();
var fileGUID = AssetDatabase.FindAssets("HTMLReporterPrefix").FirstOrDefault();
var filePath = AssetDatabase.GUIDToAssetPath(fileGUID);
var file = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
sb.Append(file.text);
sb.AppendLine($"<div class=\"Details Wordwrap\">{EditorIterationProfilerIntegration.Instance.Settings}</div>");
sb.AppendLine($"<br>");
sb.AppendLine();
sb.AppendLine($"<body>");
sb.AppendLine($"<div class=\"ToggleButton\" onclick=\"treeViewToggleAll(true);\">Expand all</div>");
sb.AppendLine($"<div class=\"ToggleButton\" onclick=\"treeViewToggleAll(false);\">Collapse all</div>");
return sb;
}
protected override StringBuilder GetMainStringBuilder(in IIterationList iterationList)
{
var sb = new StringBuilder();
if (iterationList.IterationEventRoots.Count > 0)
{
RecursiveIterationList(iterationList, ref sb);
}
else
{
sb.AppendLine($"<div>ERROR: No data to export!</div>");
}
return sb;
}
protected void RecursiveIterationList(in IIterationList iterationList, ref StringBuilder sb)
{
if (iterationList.IterationEventRoots.Count == 0)
{
return;
}
for (int i = 0; i < iterationList.IterationEventRoots.Count; ++i)
{
RecursiveIterationEventRoot(iterationList.IterationEventRoots[i], ref sb);
}
}
protected void RecursiveIterationEventRoot(in IterationEventRoot iterationEventRoot, ref StringBuilder sb)
{
double totalDuration = 0;
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0 && ed.Duration > 0)
{
totalDuration += ed.Duration;
}
}
m_ParentTotalDuration = totalDuration;
foreach (var agg in m_Aggregators)
{
agg.Reset(totalDuration);
}
var foundRoot = new List<bool>(m_Aggregators.Count);
for (int i = 0; i < foundRoot.Capacity; ++i)
{
foundRoot.Add(false);
}
var indentation1 = IndentationProvider.Get(1);
sb.AppendLine($"<div class=\"TreeViewItem TreeViewItemCollapsed\">");
sb.AppendLine(TimeDisplay(1, totalDuration));
sb.AppendLine(PercentageDisplay(1, 100));
sb.AppendLine($"{indentation1}<div class=\"NameDisplay\" onclick=\"treeViewToggle(event);\">Iteration {iterationEventRoot.IterationIndex + 1} ({iterationEventRoot.IterationEventKind})</div>");
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0)
{
RecursiveEventData(ed, iterationEventRoot, ref sb, 1, 100, foundRoot);
sb.AppendLine($"{indentation1}</div>");
}
}
sb.AppendLine(AggregateDataToString());
sb.AppendLine($"</div>");
}
protected void RecursiveEventData(in EventData ed, in IterationEventRoot parent, ref StringBuilder sb, int depth, double parentPercentage, List<bool> foundRoot)
{
var indentation1 = IndentationProvider.Get(depth);
var indentation2 = IndentationProvider.Get(depth + 1);
double percentage = ed.Duration / m_ParentTotalDuration * 100;
var currentFoundRoot = new List<bool>(foundRoot);
AggregateEventData(ed, percentage, ref currentFoundRoot);
if (parentPercentage * k_DivergenceFactor / 100 < percentage && ed.Children.Count != 0 && depth > 1 && percentage > 1)
{
RecursiveEventDataWalker(in ed, in parent, ref sb, depth, percentage, currentFoundRoot);
return;
}
bool nodeWasWritten = false;
if (percentage >= k_PrunePercentage)
{
if (ed.Children.Count > 0)
{
sb.AppendLine($"{indentation1}<div class=\"TreeViewItem TreeViewItemCollapsed\">");
sb.AppendLine(TimeDisplay(depth + 1, ed.Duration));
sb.AppendLine(PercentageDisplay(depth + 1, percentage));
sb.AppendLine($"{indentation2}<div class=\"NameDisplay\" onclick=\"treeViewToggle(event);\">{ed.Identifier}</div>");
double childrenTime = 0;
foreach (var child in ed.Children)
{
childrenTime += child.Duration;
}
var ag = FindAggregator("MISSING MARKER TIME");
if (ag != null)
{
if(ed.Duration > childrenTime)
{
ag.Aggregate(ed.Duration - childrenTime);
}
}
}
else
{
sb.AppendLine($"{indentation1}<div class=\"TreeViewItem TreeViewItemLeaf\">");
sb.AppendLine(TimeDisplay(depth + 1, ed.Duration));
sb.AppendLine(PercentageDisplay(depth + 1, percentage));
if (!string.IsNullOrEmpty(ed.Details))
{
sb.AppendLine(SimpleLabel(depth + 1, $"[{ed.Identifier}] ({ed.Details})"));
}
else
{
sb.AppendLine(SimpleLabel(depth + 1, $"[{ed.Identifier}]"));
}
}
nodeWasWritten = true;
}
else if (parentPercentage >= k_PrunePercentage && percentage < k_PrunePercentage)
{
sb.AppendLine($"{indentation1}<div class=\"TreeViewItem TreeViewItemLeaf\">");
sb.AppendLine(TimeDisplay(depth + 1, ed.Duration));
sb.AppendLine(PercentageDisplay(depth + 1, percentage));
if (!string.IsNullOrEmpty(ed.Details))
{
if (ed.Children.Count == 0)
{
sb.AppendLine(SimpleLabel(depth + 1, $"[{ed.Identifier}] ({ed.Details})"));
}
else
{
sb.AppendLine(SimpleLabel(depth + 1, $"{{{ed.Identifier}}} ({ed.Details})"));
}
}
else
{
if (ed.Children.Count == 0)
{
sb.AppendLine(SimpleLabel(depth + 1, $"[{ed.Identifier}]"));
}
else
{
sb.AppendLine(SimpleLabel(depth + 1, $"{{{ed.Identifier}}}"));
}
}
nodeWasWritten = true;
}
RecursiveEventDataWalker(in ed, in parent, ref sb, depth, percentage, currentFoundRoot);
if (nodeWasWritten && depth != 1)
{
sb.AppendLine($"{indentation1}</div>");
}
}
protected void RecursiveEventDataWalker(in EventData ed, in IterationEventRoot iterationEventRoot, ref StringBuilder sb, int depth, double percentage, List<bool> foundRoot)
{
if (ed.Children == null || ed.Children.Count == 0)
{
return;
}
foreach (var child in ed.Children)
{
RecursiveEventData(child, iterationEventRoot, ref sb, depth + 1, percentage, foundRoot);
}
}
protected static string TimeDisplay(int depth, double time)
{
return $"{IndentationProvider.Get(depth)}<div class=\"TimeDisplay\">{ToTimeString(time)}</div>";
}
protected static string PercentageDisplay(int depth, double percentage)
{
return $"{IndentationProvider.Get(depth)}<div class=\"PercentageDisplay\">{ToPercentageString(percentage)}</div>";
}
protected static string SimpleLabel(int depth, string s, string style = "")
{
if (!string.IsNullOrEmpty(style))
{
return $"{IndentationProvider.Get(depth)}<div style=\"{style}\">{s}</div>";
}
return $"{IndentationProvider.Get(depth)}<div>{s}</div>";
}
protected void AggregateEventData(EventData ed, double percentage, ref List<bool> foundRoot)
{
for (int i = 0; i < m_Aggregators.Count; ++i)
{
var agg = m_Aggregators[i];
if (agg.Pattern.IsMatch(ed.Identifier) && !foundRoot[i])
{
agg.Aggregate(TimeDisplay(agg.Depth + 1, ed.Duration) + Environment.NewLine, ed.Duration);
agg.Aggregate(PercentageDisplay(agg.Depth + 1, percentage) + Environment.NewLine);
agg.Aggregate(SimpleLabel(agg.Depth + 1, ed.Identifier + (string.IsNullOrEmpty(ed.Details) ? "" : $" ({ed.Details})"), agg.Style) + Environment.NewLine);
foundRoot[i] = true;
}
}
}
protected void AggregateData(string name, double time)
{
foreach (var agg in m_Aggregators)
{
if (agg.Pattern.IsMatch(name))
{
agg.Aggregate(time);
}
}
}
protected string AggregateDataToString()
{
var sb = new StringBuilder();
foreach (var agg in m_Aggregators)
{
sb.Append(AggregatorLabel(agg));
}
return sb.ToString();
}
protected HTMLAggregator FindAggregator(string name)
{
return m_Aggregators.FirstOrDefault(x => x.Pattern.IsMatch(name));
}
protected static StringBuilder AggregatorLabel(HTMLAggregator ag)
{
var sb = new StringBuilder();
string indentation = IndentationProvider.Get(ag.Depth);
if (ag.IsRoot)
{
sb.AppendLine($"{indentation}<div class=\"TreeViewItem TreeViewItemCollapsed\">");
sb.AppendLine($"{indentation}<div class=\"TimeDisplay\">{ToTimeString(ag.Time)}</div>");
sb.AppendLine($"{indentation}<div class=\"PercentageDisplay\">{ToPercentageString(ag.Percentage)}</div>");
sb.AppendLine($"{indentation}<div style=\"{ag.Style}\" onclick=\"treeViewToggle(event);\" class=\"NameDisplay\">{ag.Name} (Found Instances: {ag.Calls})</div>");
sb.AppendLine($"{indentation}<div class=\"TreeViewItem TreeViewItemLeaf\">");
sb.AppendLine(ag.ToString());
sb.AppendLine($"{indentation}</div>");
}
else
{
sb.AppendLine($"{indentation}<div class=\"TreeViewItem TreeViewItemLeaf\">");
sb.AppendLine($"{indentation}<div class=\"TimeDisplay\">{ToTimeString(ag.Time)}</div>");
sb.AppendLine($"{indentation}<div class=\"PercentageDisplay\">{ToPercentageString(ag.Percentage)}</div>");
sb.AppendLine($"{indentation}<div style=\"{ag.Style}\">{ag.Name} ({ag.Calls})</div>");
}
sb.AppendLine($"{indentation}</div>");
return sb;
}
public override string ToString()
{
return GetType().Name;
}
}
}
================================================
FILE: Editor/Formatters/Reporters/HTMLPerfReport.cs.meta
================================================
fileFormatVersion: 2
guid: 5982d768475803a4185fccf2a6ac8642
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/HTMLReporter.cs
================================================
using System.Text;
using UnityEditor.EditorIterationProfiler.Formatting;
using System.IO;
using System.Linq;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler
{
sealed class HTMLReporter : FileReporter
{
string m_Extension = "html";
public override string Extension => m_Extension;
string m_Name = "HTML";
public override string Name => m_Name;
double m_ParentTotalDuration;
protected override StringBuilder GetPrefixStringBuilder(in IIterationList iterationList = null)
{
var sb = new StringBuilder();
var fileGUID = AssetDatabase.FindAssets("HTMLReporterPrefix").FirstOrDefault();
var filePath = AssetDatabase.GUIDToAssetPath(fileGUID);
var file = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
sb.Append(file.text);
sb.AppendLine($"<div class=\"Details Wordwrap\">{EditorIterationProfilerIntegration.Instance.Settings}</div>");
sb.AppendLine($"<br>");
sb.AppendLine();
sb.AppendLine($"<body>");
sb.AppendLine($"<div class=\"ToggleButton\" onclick=\"treeViewToggleAll(true);\">Expand all</div>");
sb.AppendLine($"<div class=\"ToggleButton\" onclick=\"treeViewToggleAll(false);\">Collapse all</div>");
return sb;
}
protected override StringBuilder GetMainStringBuilder(in IIterationList iterationList)
{
var sb = new StringBuilder();
if (iterationList.IterationEventRoots.Count > 0)
{
RecursiveIterationList(iterationList, ref sb);
}
else
{
sb.AppendLine($"<div>ERROR: No data to export!</div>");
}
return sb;
}
void RecursiveIterationList(in IIterationList iterationList, ref StringBuilder sb)
{
if (iterationList.IterationEventRoots.Count == 0)
{
return;
}
for (int i = 0; i < iterationList.IterationEventRoots.Count; ++i)
{
RecursiveIterationEventRoot(iterationList.IterationEventRoots[i], ref sb);
}
}
void RecursiveIterationEventRoot(in IterationEventRoot iterationEventRoot, ref StringBuilder sb)
{
double totalDuration = 0;
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0 && ed.Duration > 0)
{
totalDuration += ed.Duration;
}
}
m_ParentTotalDuration = totalDuration;
var indentation1 = IndentationProvider.Get(1);
sb.AppendLine($"<div class=\"TreeViewItem TreeViewItemCollapsed\">");
sb.AppendLine(TimeDisplay(1, totalDuration));
sb.AppendLine(PercentageDisplay(1, 100));
sb.AppendLine($"{indentation1}<div class=\"NameDisplay\" onclick=\"treeViewToggle(event);\">Iteration {iterationEventRoot.IterationIndex + 1} ({iterationEventRoot.IterationEventKind})</div>");
foreach (var ed in iterationEventRoot.Events)
{
if (ed.ParentIndex < 0)
{
RecursiveEventData(ed, iterationEventRoot, ref sb, 1, 100);
sb.AppendLine($"{indentation1}</div>");
}
}
sb.AppendLine($"</div>");
}
void RecursiveEventData(in EventData ed, in IterationEventRoot parent, ref StringBuilder sb, int depth, double parentPercentage)
{
var indentation1 = IndentationProvider.Get(depth);
var indentation2 = IndentationProvider.Get(depth + 1);
double percentage = ed.Duration / m_ParentTotalDuration * 100;
if (ed.Children.Count > 0)
{
sb.AppendLine($"{indentation1}<div class=\"TreeViewItem TreeViewItemCollapsed\">");
sb.AppendLine(TimeDisplay(depth + 1, ed.Duration));
sb.AppendLine(PercentageDisplay(depth + 1, percentage));
if (!string.IsNullOrEmpty(ed.Details))
{
sb.AppendLine($"{indentation2}<div class=\"NameDisplay\" onclick=\"treeViewToggle(event);\">{ed.Identifier} ({ed.Details})</div>");
}
else
{
sb.AppendLine($"{indentation2}<div class=\"NameDisplay\" onclick=\"treeViewToggle(event);\">{ed.Identifier}</div>");
}
}
else
{
sb.AppendLine($"{indentation1}<div class=\"TreeViewItem TreeViewItemLeaf\">");
sb.AppendLine(TimeDisplay(depth + 1, ed.Duration));
sb.AppendLine(PercentageDisplay(depth + 1, percentage));
if (!string.IsNullOrEmpty(ed.Details))
{
sb.AppendLine(SimpleLabel(depth + 1, $"[{ed.Identifier}] ({ed.Details})"));
}
else
{
sb.AppendLine(SimpleLabel(depth + 1, $"[{ed.Identifier}]"));
}
}
RecursiveEventDataWalker(in ed, in parent, ref sb, depth, percentage);
if (depth != 1)
{
sb.AppendLine($"{indentation1}</div>");
}
}
void RecursiveEventDataWalker(in EventData ed, in IterationEventRoot iterationEventRoot, ref StringBuilder sb, int depth, double percentage)
{
if (ed.Children == null || ed.Children.Count == 0)
{
return;
}
foreach (var child in ed.Children)
{
RecursiveEventData(child, iterationEventRoot, ref sb, depth + 1, percentage);
}
}
string TimeDisplay(int depth, double time)
{
return $"{IndentationProvider.Get(depth)}<div class=\"TimeDisplay\">{ToTimeString(time)}</div>";
}
string PercentageDisplay(int depth, double percentage)
{
return $"{IndentationProvider.Get(depth)}<div class=\"PercentageDisplay\">{ToPercentageString(percentage)}</div>";
}
string SimpleLabel(int depth, string s, string style = "")
{
if (!string.IsNullOrEmpty(style))
{
return $"{IndentationProvider.Get(depth)}<div style=\"{style}\">{s}</div>";
}
return $"{IndentationProvider.Get(depth)}<div>{s}</div>";
}
public override string ToString()
{
return GetType().Name;
}
}
}
================================================
FILE: Editor/Formatters/Reporters/HTMLReporter.cs.meta
================================================
fileFormatVersion: 2
guid: e616717ebe9a5aa41a86a75e07d38c16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/HTMLReporterPrefix.txt
================================================
<html>
<head>
<style>
body {
font-family: monospace;
}
body > .TreeViewItem {
margin-left: 175px;
border: none;
}
.Wordwrap {
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
.Details {
font-size: 10px;
}
.TreeViewItem {
padding: 2px;
padding-left: 10px;
border-left: 1px solid black;
}
.TreeViewItem::before {
content: "-";
float: left;
padding-right: 2px;
margin-left: -10px;
}
.TreeViewItemCollapsed::before {
content: "+";
}
.TreeViewItemCollapsed > .TreeViewItem {
display: none;
}
.TreeViewItemLeaf::before {
content: none;
}
.TimeDisplay {
position:absolute;
left: 0px;
width: 95px;
text-align: right;
color: purple;
}
.PercentageDisplay{
position:absolute;
left: 120px;
text-align: right;
color: green;
}
.NameDisplay {
cursor: pointer;
}
.NameDisplay:hover {
text-decoration: underline;
color: blue;
}
.ToggleButton {
padding: 2px;
margin: 2px;
border: 1px solid black;
display: inline-block;
cursor: pointer;
}
</style>
<script>
function treeViewToggle(evt) {
if (evt.eventPhase != Event.AT_TARGET)
return;
var target = evt.target.parentNode;
var classList = target.className.split(" ");
var idx = classList.indexOf("TreeViewItemCollapsed");
if (idx < 0) {
target.className += " TreeViewItemCollapsed";
} else {
classList.splice(idx, 1);
target.className = classList.join(" ");
}
}
function treeViewToggleAll(enable) {
var elements = document.getElementsByClassName("TreeViewItem");
for (e = 0; e < elements.length; ++e) {
var elem = elements[e];
var classList = elem.className.split(" ");
if (classList.indexOf("TreeViewItemLeaf") >= 0)
continue;
var idx = classList.indexOf("TreeViewItemCollapsed");
if (enable && idx >= 0) {
classList.splice(idx, 1);
elem.className = classList.join(" ");
} else if (!enable && idx < 0) {
elem.className += " TreeViewItemCollapsed";
}
}
}
</script>
</head>
================================================
FILE: Editor/Formatters/Reporters/HTMLReporterPrefix.txt.meta
================================================
fileFormatVersion: 2
guid: fa0a687d251c5484281dc568e5a0e2ad
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters/PlaintextReporter.cs
================================================
namespace UnityEditor.EditorIterationProfiler.Formatting
{
public sealed class PlaintextReporter : FileReporter
{
string m_Extension = "txt";
public override string Extension => m_Extension;
string m_Name = "Plaintext";
public override string Name => m_Name;
IDataReporter m_El = new EditorLogReporter();
public override void Report(in IIterationList iterationList, string path)
{
ReportToFile(m_El.GetFormatString(iterationList), path);
}
public override string ToString()
{
return GetType().Name;
}
}
}
================================================
FILE: Editor/Formatters/Reporters/PlaintextReporter.cs.meta
================================================
fileFormatVersion: 2
guid: 843fc8e922ce90b4fb75e591fe507647
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters/Reporters.meta
================================================
fileFormatVersion: 2
guid: dded3bae191a0ba46be87613decab5af
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Formatters.meta
================================================
fileFormatVersion: 2
guid: 313fa6debd8d20c46ad511bfbb6b4213
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/IterationEventKind.cs
================================================
using System;
namespace UnityEditor.EditorIterationProfiler
{
public enum IterationEventKind
{
None = 0,
AssetImport,
AssetPostProcess,
ScriptCompilation,
AssemblyCompilation,
EnterPlayMode,
ExitPlayMode,
AssemblyReload,
AssemblyCompilationStart,
AssemblyCompilationFinish
}
}
================================================
FILE: Editor/IterationEventKind.cs.meta
================================================
fileFormatVersion: 2
guid: c0ea77b406086944dbb826a1c0895a29
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/IterationEventRoot.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler
{
[Serializable]
public class IterationEventRoot
{
[SerializeField]
List<EventData> m_Events = new List<EventData>();
public List<EventData> Events => m_Events;
[SerializeField]
int m_IterationIndex;
public int IterationIndex
{
get => m_IterationIndex;
set => m_IterationIndex = value;
}
[SerializeField]
IterationEventKind m_IterationEventKind;
public IterationEventKind IterationEventKind => m_IterationEventKind;
[SerializeField]
Dictionary<string, EventData> m_EventDictionary = new Dictionary<string, EventData>();
public IterationEventKind LastIterationEventKind
{
get
{
if (Events.Count == 0)
{
return IterationEventKind.None;
}
return Events.Last().Kind;
}
}
public IterationEventRoot(int index)
{
IterationIndex = index;
m_IterationEventKind = IterationEventKind.None;
}
public IterationEventRoot(int index, IterationEventKind eventKind)
{
IterationIndex = index;
m_IterationEventKind = eventKind;
}
public void Reload()
{
foreach (var eventData in Events)
{
eventData.Children = new List<EventData>();
}
foreach (var eventData in Events)
{
int parentIndex = eventData.ParentIndex;
if (parentIndex >= 0)
{
Events[parentIndex].Children.Add(eventData);
}
}
}
public EventData StartEvent(IterationEventKind kind, string identifier, string metadata)
{
int index = Events.Count;
var eventData = new EventData(kind, identifier, metadata, index);
Events.Add(eventData);
m_EventDictionary[identifier] = eventData;
return eventData;
}
public EventData StartEvent(IterationEventKind kind)
{
return StartEvent(kind, kind.ToString(), null);
}
public void FinishEvent(string identifier)
{
var eventData = FindLastEvent(identifier);
eventData?.Finish();
}
public void FinishEvent(IterationEventKind kind)
{
string identifier = kind.ToString();
FinishEvent(identifier);
}
public EventData AddChildEvent(string identifier, string metadata, double startTime, double finishTime, EventData parentEvent, EventDataFlags flags = EventDataFlags.None)
{
int index = Events.Count;
var eventData = new EventData(identifier, metadata, index, startTime, finishTime, flags);
Events.Add(eventData);
SetParent(eventData, parentEvent);
return eventData;
}
public static void SetParent(EventData child, EventData parent)
{
if (child == null)
{
throw new ArgumentNullException(nameof(child), "Argument is null");
}
if (parent == null)
{
throw new ArgumentNullException(nameof(parent), "Argument is null");
}
child.ParentIndex = parent.Index;
parent.Children.Add(child);
}
public void SetParent(EventData child, IterationEventKind kind)
{
var parent = FindLastEvent(kind);
SetParent(child, parent);
}
public EventData FindLastEvent(IterationEventKind kind)
{
string identifier = kind.ToString();
return FindLastEvent(identifier);
}
public EventData FindLastEvent(string identifier)
{
if (m_EventDictionary != null && m_EventDictionary.TryGetValue(identifier, out var eventData))
{
return eventData;
}
// If an assembly reload happens, then eventDictionary is
// empty and we search for the last event with matching
// identifier.
for (int i = Events.Count - 1; i >= 0; --i)
{
if (Events[i].Identifier == identifier)
{
return Events[i];
}
}
return null;
}
}
}
================================================
FILE: Editor/IterationEventRoot.cs.meta
================================================
fileFormatVersion: 2
guid: 6efa6c94e301cfc4da89c7584f3ceb2a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/IterationList.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace UnityEditor.EditorIterationProfiler
{
[Serializable]
class IterationList : IIterationList
{
[SerializeField]
List<IterationEventRoot> m_IterationIterationEventRoots;
public List<IterationEventRoot> IterationEventRoots => m_IterationIterationEventRoots;
public IterationEventRoot LastIterationEventRoot => m_IterationIterationEventRoots.LastOrDefault();
[SerializeField]
List<IterationEventKind> m_IterationEventKinds;
public List<IterationEventKind> IterationEventKinds => m_IterationEventKinds;
[SerializeField]
Action<IIterationList> m_Updated;
public Action<IIterationList> Updated { get; set; }
public IterationList()
{
m_IterationIterationEventRoots = new List<IterationEventRoot>();
m_IterationEventKinds = new List<IterationEventKind>();
}
public void NewIteration(IterationEventKind kind)
{
int index = IterationEventRoots.Count;
IterationEventRoots.Add(new IterationEventRoot(index, kind));
IterationEventKinds.Add(kind);
}
public void Clear()
{
IterationEventRoots.Clear();
IterationEventKinds.Clear();
NotifyUpdated();
}
public void Reload()
{
foreach (var eventDataList in IterationEventRoots)
{
eventDataList.Reload();
}
NotifyUpdated();
}
public void NotifyUpdated()
{
Updated?.Invoke(this);
}
}
}
================================================
FILE: Editor/IterationList.cs.meta
================================================
fileFormatVersion: 2
guid: 685ab7a1693ff6d4588b129ce76cef56
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/ProfilerDataCollector.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor.EditorIterationProfiler.API;
using UnityEditor.Profiling;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.Profiling;
namespace UnityEditor.EditorIterationProfiler
{
[Serializable]
public class ProfilerDataCollector : IProfilerDataCollector
{
IIterationList m_IterationList;
//static Dictionary<string, string> s_FlattenMarkers = new Dictionary<string, string>();
static Dictionary<IterationEventKind, string[]> s_KeyMarkers = new Dictionary<IterationEventKind, string[]>();
static Dictionary<string, EventDataFlags> s_MarkerFlags = new Dictionary<string, EventDataFlags>();
static Dictionary<string, string[]> s_MarkerThread = new Dictionary<string, string[]>();
[SerializeField]
List<FrameSearchData> m_FrameSearchDataList = new List<FrameSearchData>();
public ProfilerDataCollector(IIterationList iterationList)
{
Initialize(iterationList);
// Find frame where asset import kicks off compilation.
AddKeyMarkers(IterationEventKind.AssetImport, "CompilationPipeline.CompileScripts");
//AddKeyMarkers(IterationEventKind.AssemblyCompilationStart, "CompilationPipeline.CompileAssemblyStart");
//AddKeyMarkers(IterationEventKind.AssemblyCompilationFinish, "CompilationPipeline.CompileAssemblyFinish");
AddKeyMarkers(IterationEventKind.AssemblyReload, "ReloadAssemblies");
AddKeyMarkers(IterationEventKind.EnterPlayMode, "EnterPlayMode");
AddKeyMarkers(IterationEventKind.ExitPlayMode, "ExitPlayMode");
//AddFlattenMarker("ReloadAssembly", "ReloadAssemblies");
//AddFlattenMarker("BeginReloadAssembly", "ReloadAssemblies");
//AddFlattenMarker("EndReloadAssembly", "ReloadAssemblies");
string[] userCodeMarkers =
{
"AssemblyReloadEvents.OnBeforeAssemblyReload()",
"AssemblyReloadEvents.OnAfterAssemblyReload()",
"DisabledScriptedObjects",
"BackupScriptedObjects",
"RestoreManagedReferences",
"ProcessInitializeOnLoadAttributes",
"ProcessInitializeOnLoadMethodAttributes",
"AwakeScriptedObjects",
"UnloadDomain"
};
foreach (string marker in userCodeMarkers)
{
AddMarkerFlags(marker, EventDataFlags.UserCode);
}
#if UNITY_2020_3_OR_NEWER
AddThreadMarker("UnloadDomain", "Domain Unloader", "Finalizer");
#else
AddThreadMarker("UnloadDomain", "Domain unloader", "Finalizer");
#endif
}
void Initialize(IIterationList iterationList)
{
m_IterationList = iterationList;
}
public void Clear()
{
m_FrameSearchDataList.Clear();
}
public void Subscribe()
{
UnityProfiling.NewProfilerFrameRecorded += ProfilerNewFrame;
}
public void Unsubscribe()
{
UnityProfiling.NewProfilerFrameRecorded -= ProfilerNewFrame;
}
static void AddKeyMarkers(IterationEventKind iterationEventKind, params string[] markers)
{
s_KeyMarkers[iterationEventKind] = markers;
}
static string[] GetKeyMarkers(IterationEventKind iterationEventKind)
{
if (s_KeyMarkers.TryGetValue(iterationEventKind, out string[] marker))
{
return marker;
}
return null;
}
//static void AddFlattenMarker(string marker, string parentMarker)
//{
// s_FlattenMarkers[marker] = parentMarker;
//}
static void AddMarkerFlags(string marker, EventDataFlags flags)
{
s_MarkerFlags[marker] = flags;
}
static void AddThreadMarker(string marker, params string[] threadNames)
{
s_MarkerThread[marker] = threadNames;
}
public void Collect(IterationEventKind iterationEventKind, IterationEventRoot iterationEventRoot, EventData rootEvent)
{
var frameSearchData = new FrameSearchData
{
IterationEventKind = iterationEventKind,
EventListIndex = iterationEventRoot.IterationIndex,
EventDataIndex = rootEvent.Index,
MaxNumFrames = 600
};
m_FrameSearchDataList.Add(frameSearchData);
#if DEVELOPMENT_BUILD
Debug.Log($"Starting to look for {iterationEventKind}");
#endif
}
void ProfilerNewFrame(int connectionId, int newFrameIndex)
{
// Remove frames which exceeded the search limit.
for (var i = m_FrameSearchDataList.Count - 1; i >= 0; --i)
{
m_FrameSearchDataList[i].MaxNumFrames -= 1;
if (m_FrameSearchDataList[i].MaxNumFrames <= 0)
{
#if DEVELOPMENT_BUILD
Debug.Log($"Stopping search for event {m_FrameSearchDataList[i].IterationEventKind}");
#endif
m_FrameSearchDataList.RemoveAt(i);
}
}
if (m_FrameSearchDataList.Count == 0)
{
return;
}
var frameData = UnityProfiling.GetFrame(newFrameIndex, 0);
if (!frameData.valid)
{
#if DEVELOPMENT_BUILD
Debug.LogErrorFormat($"Unable to retrieve profiler data for frame {newFrameIndex}");
#endif
return;
}
var markerData = new MarkerData(m_FrameSearchDataList.Count);
for (var i = 0; i < markerData.Length; ++i)
{
var frameSearchData = m_FrameSearchDataList[i];
frameSearchData.MaxNumFrames -= 1;
markerData.Markers[i] = GetKeyMarkers(frameSearchData.IterationEventKind);
}
var framesNotFound = new List<FrameSearchData>();
for (int i = 0; i < m_FrameSearchDataList.Count; ++i)
{
if (markerData.FrameIndices[i] == 0)
{
framesNotFound.Add(m_FrameSearchDataList[i]);
}
}
#if DEVELOPMENT_BUILD
Debug.Log($"Searching for events {string.Join(",", framesNotFound.Select(f => f.IterationEventKind.ToString()).ToArray())} in frame {newFrameIndex}");
#endif
if (!FindMarkersInFrameData(frameData, frameData.GetRootItemID(), markerData, ProfilerDriver.deepProfiling ? 12 : 8))
{
#if DEVELOPMENT_BUILD
Debug.LogWarning($"Didn't find all markers in {newFrameIndex}");
#endif
return;
}
var iterationListUpdated = false;
for (int i = markerData.Length - 1; i >= 0; --i)
{
var frameSearchData = m_FrameSearchDataList[i];
if (markerData.SampleIds[i] == UnityProfiling.InvalidSampleId)
{
if (frameSearchData.MaxNumFrames <= 0)
{
#if DEVELOPMENT_BUILD
Debug.Log($"Stopping search for event {frameSearchData.IterationEventKind}");
#endif
m_FrameSearchDataList.RemoveAt(i);
}
continue;
}
#if DEVELOPMENT_BUILD
Debug.Log($"Reading profiling data for event {frameSearchData.IterationEventKind} from frame {markerData.FrameIndices[i]}");
#endif
var eventDataList = m_IterationList.IterationEventRoots[frameSearchData.EventListIndex];
var eventData = eventDataList.Events[frameSearchData.EventDataIndex];
ReadProfilingData(eventDataList, eventData, markerData.FrameData[i], markerData.FrameData[i].GetRootItemID(), EventDataFlags.None, false);
eventData.SetStartFinishTimeFromChildren();
eventData.PostProcess();
iterationListUpdated = true;
m_FrameSearchDataList.RemoveAt(i);
}
if (iterationListUpdated)
{
m_IterationList.NotifyUpdated();
}
}
internal static void ReadProfilingData(IterationEventRoot iterationEventRoot, EventData parentEventData, HierarchyFrameDataView frameData, int sampleId, EventDataFlags flags, bool parentHasSingleChild)
{
double duration = frameData.GetItemColumnDataAsDouble(sampleId, HierarchyFrameDataView.columnTotalTime);
if (duration < 0.01)
{
return;
}
string markerName = frameData.GetItemName(sampleId);
double startTime = frameData.GetItemColumnDataAsDouble(sampleId, HierarchyFrameDataView.columnStartTime);
double finishTime = startTime + duration;
int metadataCount = frameData.GetItemMetadataCount(sampleId);
var sb = new StringBuilder();
sb.Append("GC Alloc: " + frameData.GetItemColumnData(sampleId, 4) + "; ");
sb.Append("Calls: " + frameData.GetItemColumnData(sampleId, 3) + "; ");
if (metadataCount > 0)
{
sb.Append("Metadata: ");
for (var i = 0; i < metadataCount; ++i)
{
sb.Append(frameData.GetItemMetadata(sampleId, i));
sb.Append("; ");
}
}
var markerMetadata = sb.Replace(',', ';').Remove(sb.Length - 2, 1).ToString().Trim();
if (s_MarkerFlags.TryGetValue(markerName, out var eventMarkerFlags))
{
flags |= eventMarkerFlags;
}
var childEvent = iterationEventRoot.AddChildEvent(markerName, markerMetadata, startTime, finishTime, parentEventData, flags);
if (s_MarkerThread.TryGetValue(markerName, out string[] threadNames))
{
foreach (string threadName in threadNames)
{
var threadFrameData = UnityProfiling.GetFrame(frameData.frameIndex, threadName);
var threadEvent = iterationEventRoot.AddChildEvent($"Thread: {threadName}", markerMetadata, parentEventData.StartTime, parentEventData.FinishTime, childEvent, flags);
var threadChildIds = new List<int>();
threadFrameData.GetItemChildren(threadFrameData.GetRootItemID(), threadChildIds);
foreach (int childId in threadChildIds)
{
ReadProfilingData(iterationEventRoot, threadEvent, threadFrameData, childId, flags, threadChildIds.Count == 1);
}
threadEvent.SetStartFinishTimeFromChildren();
}
}
var childIds = new List<int>();
frameData.GetItemChildren(sampleId, childIds);
foreach (int childId in childIds)
{
ReadProfilingData(iterationEventRoot, childEvent, frameData, childId, flags, childIds.Count == 1);
}
}
static bool FindMarkersInFrameData(HierarchyFrameDataView frameData, int parentId, MarkerData markerData, int maxDepth)
{
if (maxDepth == 0)
{
return false;
}
var childrenIds = new List<int>();
frameData.GetItemChildren(parentId, childrenIds);
string[][] markers = markerData.Markers;
int[] sampleIds = markerData.SampleIds;
int[] frameIndices = markerData.FrameIndices;
foreach (int childId in childrenIds)
{
string name = frameData.GetItemName(childId);
for (var i = 0; i < markers.Length; ++i)
{
if (markers[i] == null)
{
continue;
}
string[] localKeyMarkers = markers[i];
for (var j = 0; j < localKeyMarkers.Length; ++j)
{
if (name == localKeyMarkers[j])
{
sampleIds[i] = childId;
frameIndices[i] = frameData.frameIndex;
markerData.FrameData[i] = frameData;
}
}
}
if (markerData.FoundAllSampleIds)
{
return true;
}
if (FindMarkersInFrameData(frameData, childId, markerData, maxDepth - 1))
{
return true;
}
}
return false;
}
[Serializable]
public class FrameSearchData
{
public int EventDataIndex;
public int EventListIndex;
public IterationEventKind IterationEventKind;
public int MaxNumFrames;
}
struct MarkerData
{
public string[][] Markers;
public int[] SampleIds;
public int[] FrameIndices;
public HierarchyFrameDataView[] FrameData;
public MarkerData(int length)
{
Markers = new string[length][];
SampleIds = new int[length];
FrameIndices = new int[length];
FrameData = new HierarchyFrameDataView[length];
for (var i = 0; i < length; ++i)
{
SampleIds[i] = UnityProfiling.InvalidSampleId;
}
}
public bool FoundAllSampleIds
{
get
{
for (var i = 0; i < Length; ++i)
{
if (SampleIds[i] == UnityProfiling.InvalidSampleId)
{
return false;
}
}
return true;
}
}
public int Length => Markers.Length;
}
}
}
================================================
FILE: Editor/ProfilerDataCollector.cs.meta
================================================
fileFormatVersion: 2
guid: d1e3dc04d1e8e8344a237bfc5e3b756b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/Unity.EditorIterationProfiler.Editor.asmdef
================================================
{
"name": "Unity.EditorIterationProfiler.Editor",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
================================================
FILE: Editor/Unity.EditorIterationProfiler.Editor.asmdef.meta
================================================
fileFormatVersion: 2
guid: 00680d720d027674dbb1d8c51e1aaa52
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/UnityEditorEvents.cs
================================================
using System;
using System.IO;
using UnityEditor.Compilation;
namespace UnityEditor.EditorIterationProfiler
{
static class UnityEditorEvents
{
public enum Event
{
None = 0,
ScriptCompilationStarted,
ScriptCompilationFinished,
AssemblyCompilationStarted,
AssemblyCompilationFinished,
AssemblyReloadStarted,
AssemblyReloadFinished,
EnteringPlayMode,
EnteredPlayMode,
ExitingPlayMode,
ExitedPlayMode
}
public static event Action<Event, string> EditorEvent;
public static void Subscribe()
{
CompilationPipeline.compilationStarted += ScriptCompilationStarted;
CompilationPipeline.compilationFinished += ScriptCompilationFinished;
CompilationPipeline.assemblyCompilationStarted += AssemblyCompilationStarted;
CompilationPipeline.assemblyCompilationFinished += AssemblyCompilationFinished;
AssemblyReloadEvents.beforeAssemblyReload += AssemblyReloadStarted;
AssemblyReloadEvents.afterAssemblyReload += AssemblyReloadFinished;
EditorApplication.playModeStateChanged += PlayModeStateChanged;
}
public static void Unsubscribe()
{
CompilationPipeline.compilationStarted -= ScriptCompilationStarted;
CompilationPipeline.compilationFinished -= ScriptCompilationFinished;
CompilationPipeline.assemblyCompilationStarted -= AssemblyCompilationStarted;
CompilationPipeline.assemblyCompilationFinished -= AssemblyCompilationFinished;
AssemblyReloadEvents.beforeAssemblyReload -= AssemblyReloadStarted;
AssemblyReloadEvents.afterAssemblyReload -= AssemblyReloadFinished;
EditorApplication.playModeStateChanged -= PlayModeStateChanged;
}
static void ScriptCompilationStarted(object obj)
{
EditorEvent?.Invoke(Event.ScriptCompilationStarted, null);
}
static void ScriptCompilationFinished(object obj)
{
EditorEvent?.Invoke(Event.ScriptCompilationFinished, null);
}
static void AssemblyCompilationStarted(string assembly)
{
EditorEvent?.Invoke(Event.AssemblyCompilationStarted, Path.GetFileName(assembly));
}
static void AssemblyCompilationFinished(string assembly, CompilerMessage[] messages)
{
EditorEvent?.Invoke(Event.AssemblyCompilationFinished, Path.GetFileName(assembly));
}
static void AssemblyReloadStarted()
{
EditorEvent?.Invoke(Event.AssemblyReloadStarted, null);
}
static void AssemblyReloadFinished()
{
EditorEvent?.Invoke(Event.AssemblyReloadFinished, null);
}
static void PlayModeStateChanged(PlayModeStateChange state)
{
switch (state)
{
case PlayModeStateChange.ExitingEditMode:
{
EditorEvent?.Invoke(Event.EnteringPlayMode, null);
}
break;
case PlayModeStateChange.EnteredPlayMode:
{
EditorEvent?.Invoke(Event.EnteredPlayMode, null);
}
break;
case PlayModeStateChange.ExitingPlayMode:
{
EditorEvent?.Invoke(Event.ExitingPlayMode, null);
}
break;
case PlayModeStateChange.EnteredEditMode:
{
EditorEvent?.Invoke(Event.ExitedPlayMode, null);
}
break;
}
}
}
}
================================================
FILE: Editor/UnityEditorEvents.cs.meta
================================================
fileFormatVersion: 2
guid: 521d993316e2dc54f9f64b52fe96eadf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor/UnityProfiling.cs
================================================
using System;
using UnityEditor.Profiling;
using UnityEditorInternal;
namespace UnityEditor.EditorIterationProfiler
{
static class UnityProfiling
{
public static bool EditorProfilingEnabled
{
get => ProfilerDriver.enabled && ProfilerDriver.profileEditor;
set
{
ProfilerDriver.enabled = value;
ProfilerDriver.profileEditor = value;
}
}
public static void SetProfileDeepScripts(bool deep)
{
if (ProfilerDriver.deepProfiling == deep)
return;
bool doApply = true;
// When enabling / disabling deep script profiling we need to reload scripts. In play mode this might be intrusive, so we ask the user first.
if (EditorApplication.isPlaying)
{
if (deep)
{
doApply = EditorUtility.DisplayDialog("Enable deep script profiling", "Enabling deep profiling requires reloading scripts.", "Reload", "Cancel");
}
else
{
doApply = EditorUtility.DisplayDialog("Disable deep script profiling", "Disabling deep profiling requires reloading all scripts", "Reload", "Cancel");
}
}
if (doApply)
{
EditorIterationProfilerAnalytics.SendInteractionEvent(EditorProfilingEnabled, EditorApplication.isPlaying, ProfilerDriver.deepProfiling, EditorIterationProfilerIntegration.Instance.Settings.Flatten, EditorIterationProfilerIntegration.Instance.Settings.UserCode);
ProfilerDriver.deepProfiling = deep;
EditorPrefs.SetBool(EditorIterationProfilerWindow.Styles.k_EnableDeepProfile, deep);
EditorIterationProfilerIntegration.Instance.Settings.DeepProfile = deep;
EditorUtility.RequestScriptReload();
}
}
public static int InvalidSampleId => HierarchyFrameDataView.invalidSampleId;
public static event Action<int, int> NewProfilerFrameRecorded
{
add => ProfilerDriver.NewProfilerFrameRecorded += value;
remove => ProfilerDriver.NewProfilerFrameRecorded -= value;
}
public static HierarchyFrameDataView GetFrame(int frameIndex, int threadIndex)
{
var frame = ProfilerDriver.GetHierarchyFrameDataView(frameIndex, threadIndex, HierarchyFrameDataView.ViewModes.MergeSamplesWithTheSameName, HierarchyFrameDataView.columnTotalTime, false);
return frame;
}
public static HierarchyFrameDataView GetFrame(int frameIndex, string threadName)
{
var iter = new ProfilerFrameDataIterator();
iter.SetRoot(frameIndex, 0);
int threadCount = iter.GetThreadCount(frameIndex);
for (var i = 0; i < threadCount; ++i)
{
iter.SetRoot(frameIndex, i);
string currentThreadName = iter.GetThreadName();
if (currentThreadName.Equals(threadName, StringComparison.OrdinalIgnoreCase))
{
iter.Dispose();
return GetFrame(frameIndex, i);
}
}
iter.Dispose();
throw new ArgumentException($"Could not find thread named '{threadName}'. Depending on the Unity version, it could have been renamed.");
}
}
}
================================================
FILE: Editor/UnityProfiling.cs.meta
================================================
fileFormatVersion: 2
guid: dc5baee3fb0bc9f41ba836bff674eb06
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: Editor.meta
================================================
fileFormatVersion: 2
guid: 9949f7c4ae59ee7499a083d831233f16
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: LICENSE.md
================================================
Editor Iteration Profiler copyright © 2020 Unity Technologies ApS
Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](https://unity3d.com/legal/licenses/Unity_Companion_License).
Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions.
================================================
FILE: LICENSE.md.meta
================================================
fileFormatVersion: 2
guid: 0515e52add3ab464880c7466bcf136b8
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: README.md
================================================
# Editor Iteration Profiler
Assists in capturing frames from the Profiler of Domain Reloads in the Unity Editor. Compatible with Unity 2019.3+.
# Please see the forum post for details on how to use, gotchas, etc. https://forum.unity.com/threads/introducing-the-editor-iteration-profiler.908390/
================================================
FILE: README.md.meta
================================================
fileFormatVersion: 2
guid: 41ae1fb9d1a93684bb23091b2c54ad2b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
================================================
FILE: package.json
================================================
{
"name": "com.unity.editoriterationprofiler",
"displayName":"Editor Iteration Profiler",
"version": "0.1.2-preview",
"unity": "2019.3",
"description": "The Editor Iteration Profiler is an Editor tool which monitors domain reloads. It makes use of the Profiler and works by collecting and storing the relevant frames of the domain reload.\n\nMain features:\n▪ Enter/Exit playmode domain reload monitoring\n▪ Script Compilation monitoring\n▪ Ability to export its data or Profiler data to a number of formats such as CSV, HTML, JSON, etc.\n",
"dependencies": {
}
}
================================================
FILE: package.json.meta
================================================
fileFormatVersion: 2
guid: 9d114ba67f600c34994534b2b6994a8a
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
gitextract_9o_f0g0j/ ├── .gitignore ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── CONTRIBUTING.md ├── CONTRIBUTING.md.meta ├── Documentation~/ │ ├── TableOfContents.md │ ├── editor-iteration-profiler.md │ ├── exporting-data.md │ └── index.md ├── Editor/ │ ├── DataCollector.cs │ ├── DataCollector.cs.meta │ ├── EditorIterationProfiler.API/ │ │ ├── IEditorIterationProfilerController.cs │ │ ├── IEditorIterationProfilerController.cs.meta │ │ ├── IEventSubscriber.cs │ │ ├── IEventSubscriber.cs.meta │ │ ├── IIterationList.cs │ │ ├── IIterationList.cs.meta │ │ ├── IProfilerDataCollector.cs │ │ └── IProfilerDataCollector.cs.meta │ ├── EditorIterationProfiler.API.meta │ ├── EditorIterationProfilerAnalytics.cs │ ├── EditorIterationProfilerAnalytics.cs.meta │ ├── EditorIterationProfilerController.cs │ ├── EditorIterationProfilerController.cs.meta │ ├── EditorIterationProfilerIntegration.cs │ ├── EditorIterationProfilerIntegration.cs.meta │ ├── EditorIterationProfilerSettings.cs │ ├── EditorIterationProfilerSettings.cs.meta │ ├── EditorIterationProfilerTreeView.cs │ ├── EditorIterationProfilerTreeView.cs.meta │ ├── EditorIterationProfilerWindow.cs │ ├── EditorIterationProfilerWindow.cs.meta │ ├── EventData.cs │ ├── EventData.cs.meta │ ├── Formatters/ │ │ ├── Aggregator.cs │ │ ├── Aggregator.cs.meta │ │ ├── DataReporterProvider.cs │ │ ├── DataReporterProvider.cs.meta │ │ ├── DataReporters.cs │ │ ├── DataReporters.cs.meta │ │ ├── FileReporter.cs │ │ ├── FileReporter.cs.meta │ │ ├── Formatter.cs │ │ ├── Formatter.cs.meta │ │ ├── IndentationProvider.cs │ │ ├── IndentationProvider.cs.meta │ │ ├── Reporters/ │ │ │ ├── CSVReporter.cs │ │ │ ├── CSVReporter.cs.meta │ │ │ ├── ChromeTracingReporter.cs │ │ │ ├── ChromeTracingReporter.cs.meta │ │ │ ├── EditorLogReporter.cs │ │ │ ├── EditorLogReporter.cs.meta │ │ │ ├── HTMLPerfReport.cs │ │ │ ├── HTMLPerfReport.cs.meta │ │ │ ├── HTMLReporter.cs │ │ │ ├── HTMLReporter.cs.meta │ │ │ ├── HTMLReporterPrefix.txt │ │ │ ├── HTMLReporterPrefix.txt.meta │ │ │ ├── PlaintextReporter.cs │ │ │ └── PlaintextReporter.cs.meta │ │ └── Reporters.meta │ ├── Formatters.meta │ ├── IterationEventKind.cs │ ├── IterationEventKind.cs.meta │ ├── IterationEventRoot.cs │ ├── IterationEventRoot.cs.meta │ ├── IterationList.cs │ ├── IterationList.cs.meta │ ├── ProfilerDataCollector.cs │ ├── ProfilerDataCollector.cs.meta │ ├── Unity.EditorIterationProfiler.Editor.asmdef │ ├── Unity.EditorIterationProfiler.Editor.asmdef.meta │ ├── UnityEditorEvents.cs │ ├── UnityEditorEvents.cs.meta │ ├── UnityProfiling.cs │ └── UnityProfiling.cs.meta ├── Editor.meta ├── LICENSE.md ├── LICENSE.md.meta ├── README.md ├── README.md.meta ├── package.json └── package.json.meta
SYMBOL INDEX (242 symbols across 30 files)
FILE: Editor/DataCollector.cs
class DataCollector (line 7) | [Serializable]
method DataCollector (line 13) | public DataCollector(IProfilerDataCollector profilerCollector, IIterat...
method Initialize (line 18) | void Initialize(IProfilerDataCollector profilerCollector, IIterationLi...
method Subscribe (line 24) | public void Subscribe()
method Unsubscribe (line 30) | public void Unsubscribe()
method EditorEvent (line 36) | void EditorEvent(UnityEditorEvents.Event evt, string data)
FILE: Editor/EditorIterationProfiler.API/IEditorIterationProfilerController.cs
type IEditorIterationProfilerController (line 3) | public interface IEditorIterationProfilerController
FILE: Editor/EditorIterationProfiler.API/IEventSubscriber.cs
type IEventSubscriber (line 3) | public interface IEventSubscriber
method Subscribe (line 5) | void Subscribe();
method Unsubscribe (line 6) | void Unsubscribe();
FILE: Editor/EditorIterationProfiler.API/IIterationList.cs
type IIterationList (line 7) | public interface IIterationList
method NewIteration (line 13) | void NewIteration(IterationEventKind kind);
method NotifyUpdated (line 14) | void NotifyUpdated();
FILE: Editor/EditorIterationProfiler.API/IProfilerDataCollector.cs
type IProfilerDataCollector (line 3) | public interface IProfilerDataCollector : IEventSubscriber
method Collect (line 5) | void Collect(IterationEventKind iterationEventKind, IterationEventRoot...
method Clear (line 6) | void Clear();
FILE: Editor/EditorIterationProfilerAnalytics.cs
class EditorIterationProfilerAnalytics (line 8) | class EditorIterationProfilerAnalytics
method EnableAnalytics (line 19) | static bool EnableAnalytics()
type ExportStatus (line 37) | internal enum ExportStatus
type ExportType (line 44) | internal enum ExportType
type ExportEventData (line 53) | struct ExportEventData
type InteractionEventData (line 61) | struct InteractionEventData
method SendExportEvent (line 70) | public static void SendExportEvent(string format, string type, string ...
method SendInteractionEvent (line 88) | public static void SendInteractionEvent(bool state, bool isPlaying, bo...
FILE: Editor/EditorIterationProfilerController.cs
class EditorIterationProfilerController (line 8) | public class EditorIterationProfilerController : ScriptableObject, IEdit...
method EditorIterationProfilerController (line 29) | public EditorIterationProfilerController()
method EditorIterationProfilerController (line 42) | public EditorIterationProfilerController(IIterationList iterationList,...
method OnEnable (line 55) | void OnEnable()
method OnDisable (line 61) | void OnDisable()
method Initialize (line 67) | internal void Initialize()
method Clear (line 72) | public void Clear()
FILE: Editor/EditorIterationProfilerIntegration.cs
class EditorIterationProfilerIntegration (line 8) | [InitializeOnLoad]
method EditorIterationProfilerIntegration (line 26) | static EditorIterationProfilerIntegration()
method Initialize (line 31) | internal static void Initialize()
method FindOrCreateInstance (line 36) | static void FindOrCreateInstance()
method Clear (line 53) | public static void Clear()
method PurgeScriptableObjects (line 59) | [MenuItem("Window/Analysis/Editor Iteration Profiler/Purge Caches", pr...
FILE: Editor/EditorIterationProfilerSettings.cs
class EditorIterationProfilerSettings (line 8) | [Serializable]
method ToString (line 30) | public override string ToString()
FILE: Editor/EditorIterationProfilerTreeView.cs
class EditorIterationProfilerTreeViewItem (line 10) | [Serializable]
class EditorIterationProfilerTreeView (line 23) | public class EditorIterationProfilerTreeView : TreeView
type ColumnId (line 25) | enum ColumnId
method EditorIterationProfilerTreeView (line 61) | public EditorIterationProfilerTreeView(TreeViewState state, MultiColum...
method OnSortingChanged (line 79) | void OnSortingChanged(MultiColumnHeader multiColumnHeader)
method Sort (line 94) | static void Sort(IList<TreeViewItem> rows, ColumnId columnId, bool asc...
method SortHierarchical (line 128) | static void SortHierarchical(TreeViewItem root, ColumnId columnId, boo...
method SortItems (line 138) | static void SortItems(IList<TreeViewItem> children, ColumnId columnId,...
method DoubleClickedItem (line 177) | protected override void DoubleClickedItem(int id)
method ClearSearch (line 191) | internal void ClearSearch()
method BuildRoot (line 196) | protected override TreeViewItem BuildRoot()
method ShouldAddTreeViewItem (line 243) | static bool ShouldAddTreeViewItem(EventData eventData, EventDataFlags ...
method AddEventDataRecursive (line 286) | static void AddEventDataRecursive(EventData eventData, List<TreeViewIt...
method RowGUI (line 311) | protected override void RowGUI(RowGUIArgs args)
method CellGUI (line 321) | void CellGUI(Rect cellRect, EditorIterationProfilerTreeViewItem item, ...
method CreateDefaultMultiColumnHeaderState (line 349) | public static MultiColumnHeaderState CreateDefaultMultiColumnHeaderSta...
class ExtensionMethods (line 388) | static class ExtensionMethods
method Order (line 390) | public static IOrderedEnumerable<T> Order<T, TKey>(this IEnumerable<T>...
method ThenBy (line 400) | public static IOrderedEnumerable<T> ThenBy<T, TKey>(this IOrderedEnume...
FILE: Editor/EditorIterationProfilerWindow.cs
class EditorIterationProfilerWindow (line 15) | public class EditorIterationProfilerWindow : EditorWindow
class Styles (line 17) | internal static class Styles
method ShowProfilerWindow (line 58) | [MenuItem("Window/Analysis/Editor Iteration Profiler/Show Window", pri...
method OnEnable (line 65) | void OnEnable()
method OnEnableInitialize (line 71) | void OnEnableInitialize()
method DrawToolbar (line 110) | void DrawToolbar()
method ReportMultipleFrames (line 225) | public static void ReportMultipleFrames(IFileDataReporter reporter, in...
method ReportSelectedFrame (line 283) | static void ReportSelectedFrame(IFileDataReporter reporter, int curren...
method ReportAllExtensions (line 323) | static void ReportAllExtensions(IIterationList iterationList)
method ReportExtension (line 336) | static void ReportExtension(IFileDataReporter fileReporterType, IItera...
method DrawSearchBar (line 374) | void DrawSearchBar()
method DrawTreeView (line 394) | void DrawTreeView()
method OnLostFocus (line 400) | void OnLostFocus()
method OnGUI (line 405) | void OnGUI()
method InitializeButtonStateFromPrefs (line 419) | static void InitializeButtonStateFromPrefs()
method InitializeHeaderStateFromPrefs (line 445) | static void InitializeHeaderStateFromPrefs(MultiColumnHeaderState state)
method UpdatePrefs (line 469) | void UpdatePrefs()
method DeleteAllEIPPrefKeys (line 477) | [MenuItem("Window/Analysis/Editor Iteration Profiler/Clear Editor Pref...
class ProfilerMultiFrameSelector (line 494) | class ProfilerMultiFrameSelector : EditorWindow
method OpenWindow (line 507) | static void OpenWindow()
method Initialize (line 512) | public void Initialize(IFileDataReporter exporter)
method OnDestroy (line 520) | public void OnDestroy()
method OnEnable (line 525) | void OnEnable()
method OnGUI (line 534) | void OnGUI()
FILE: Editor/EventData.cs
type EventDataFlags (line 9) | [Flags]
class EventData (line 17) | [Serializable]
method EventData (line 67) | public EventData(IterationEventKind kind, string identifier, string me...
method EventData (line 79) | public EventData(string identifier, string metadata, int index, double...
method SetStartTime (line 91) | public void SetStartTime()
method Finish (line 97) | public void Finish()
method SetStartFinishTimeFromChildren (line 105) | public void SetStartFinishTimeFromChildren()
method PostProcess (line 122) | public void PostProcess(bool flatten = false)
FILE: Editor/Formatters/Aggregator.cs
class Aggregator (line 8) | public class Aggregator
method Aggregator (line 21) | public Aggregator(int depth, string name, Regex pattern)
method Aggregate (line 33) | public void Aggregate(string s, bool isCall = false)
method Aggregate (line 43) | public void Aggregate(double time)
method Aggregate (line 49) | public void Aggregate(string s, double time)
method Reset (line 55) | public void Reset()
method Reset (line 63) | public void Reset(double totalTime)
method ToString (line 71) | public override string ToString()
class HTMLAggregator (line 77) | public class HTMLAggregator : Aggregator
method HTMLAggregator (line 81) | public HTMLAggregator(int depth, string name, Regex pattern, string st...
FILE: Editor/Formatters/DataReporterProvider.cs
type IDataReporterProvider (line 9) | public interface IDataReporterProvider
method GetAllReporters (line 11) | IList<T> GetAllReporters<T>() where T : IDataReporter;
method TryGetReporter (line 12) | T TryGetReporter<T>(Type type) where T : IDataReporter;
method IsFileExtensionSupported (line 13) | bool IsFileExtensionSupported(string extension);
method TryGetDataReporter (line 14) | IDataReporter TryGetDataReporter(string typeName);
method TryGetDataFileReporter (line 15) | IFileDataReporter TryGetDataFileReporter(string typeName);
class DataReporterProvider (line 18) | public class DataReporterProvider : IDataReporterProvider
method DataReporterProvider (line 23) | public DataReporterProvider()
method InitializeDataFileReporters (line 30) | void InitializeDataFileReporters()
method InitializeDataReporters (line 54) | void InitializeDataReporters()
method GetAllReporters (line 72) | public IList<T> GetAllReporters<T>() where T : IDataReporter
method TryGetReporter (line 87) | public T TryGetReporter<T>(Type type) where T : IDataReporter
method TryGetDataReporter (line 102) | public IDataReporter TryGetDataReporter(string typeName)
method TryGetDataFileReporter (line 107) | public IFileDataReporter TryGetDataFileReporter(string typeName)
method IsFileExtensionSupported (line 112) | public bool IsFileExtensionSupported(string extension)
method SanitizeExtension (line 117) | static string SanitizeExtension(string extension)
FILE: Editor/Formatters/DataReporters.cs
type IDataReporter (line 3) | public interface IDataReporter
method GetFormatString (line 5) | string GetFormatString(in IIterationList iterationList);
method Report (line 6) | void Report(in IIterationList iterationList, string path = null);
type IFileDataReporter (line 9) | public interface IFileDataReporter : IDataReporter
method Report (line 13) | new void Report(in IIterationList iterationList, string path);
FILE: Editor/Formatters/FileReporter.cs
class FileReporter (line 7) | public abstract class FileReporter : Formatter, IFileDataReporter
method Report (line 15) | public virtual void Report(in IIterationList iterationList, string path)
method ReportToFile (line 20) | protected virtual void ReportToFile(string message, string path)
method ToString (line 32) | public abstract override string ToString();
FILE: Editor/Formatters/Formatter.cs
class Formatter (line 7) | public abstract class Formatter
method GetFormatString (line 9) | public virtual string GetFormatString(in IIterationList iterationList)
method GetPrefixStringBuilder (line 16) | protected virtual StringBuilder GetPrefixStringBuilder(in IIterationLi...
method GetMainStringBuilder (line 21) | protected virtual StringBuilder GetMainStringBuilder(in IIterationList...
method GetPostfixStringBuilder (line 33) | protected virtual StringBuilder GetPostfixStringBuilder(in IIterationL...
method RecursiveIterationList (line 38) | protected virtual void RecursiveIterationList(in IIterationList iterat...
method RecursiveIterationEventRoot (line 51) | protected virtual void RecursiveIterationEventRoot(in IterationEventRo...
method RecursiveEventData (line 62) | protected virtual void RecursiveEventData(in EventData ed, in Iteratio...
method RecursiveEventDataWalker (line 67) | protected virtual void RecursiveEventDataWalker(in EventData ed, in It...
method ToTimeString (line 84) | public static string ToTimeString(double time)
method ToPercentageString (line 89) | public static string ToPercentageString(double percentage)
FILE: Editor/Formatters/IndentationProvider.cs
class IndentationProvider (line 7) | public static class IndentationProvider
method Get (line 12) | public static string Get(int count)
FILE: Editor/Formatters/Reporters/CSVReporter.cs
class CSVReporter (line 5) | sealed class CSVReporter : FileReporter
method GetPrefixStringBuilder (line 13) | protected override StringBuilder GetPrefixStringBuilder(in IIterationL...
method RecursiveIterationList (line 23) | protected override void RecursiveIterationList(in IIterationList itera...
method RecursiveEventData (line 33) | protected override void RecursiveEventData(in EventData ed, in Iterati...
method ToString (line 47) | public override string ToString()
FILE: Editor/Formatters/Reporters/ChromeTracingReporter.cs
class ChromeTracingReporter (line 7) | sealed class ChromeTracingReporter : FileReporter
method GetPrefixStringBuilder (line 17) | protected override StringBuilder GetPrefixStringBuilder(in IIterationL...
method GetMainStringBuilder (line 33) | protected override StringBuilder GetMainStringBuilder(in IIterationLis...
method GetPostfixStringBuilder (line 55) | protected override StringBuilder GetPostfixStringBuilder(in IIteration...
method RecursiveIterationEventRoot (line 65) | protected override void RecursiveIterationEventRoot(in IterationEventR...
method RecursiveEventData (line 90) | void RecursiveEventData(in EventData ed, in IterationEventRoot iterati...
method RecursiveEventDataWalker (line 100) | void RecursiveEventDataWalker(in EventData ed, in IterationEventRoot i...
method DurationEvent (line 117) | string DurationEvent(string identifier, string pid, string tid, string...
method MetadataEvent (line 122) | static string MetadataEvent(string identifier, string pid, string tid,...
method ToString (line 127) | public override string ToString()
FILE: Editor/Formatters/Reporters/EditorLogReporter.cs
class EditorLogReporter (line 6) | public class EditorLogReporter : Formatter, IDataReporter
method GetPrefixStringBuilder (line 8) | protected override StringBuilder GetPrefixStringBuilder(in IIterationL...
method RecursiveIterationEventRoot (line 18) | protected override void RecursiveIterationEventRoot(in IterationEventR...
method RecursiveEventData (line 40) | protected override void RecursiveEventData(in EventData ed, in Iterati...
method Report (line 49) | public void Report(in IIterationList iterationList, string path = null)
FILE: Editor/Formatters/Reporters/HTMLPerfReport.cs
class HTMLPerfReporter (line 11) | public class HTMLPerfReporter : FileReporter
method HTMLPerfReporter (line 29) | public HTMLPerfReporter()
method GetFormatString (line 42) | public override string GetFormatString(in IIterationList iterationList)
method GetPrefixStringBuilder (line 49) | protected override StringBuilder GetPrefixStringBuilder(in IIterationL...
method GetMainStringBuilder (line 70) | protected override StringBuilder GetMainStringBuilder(in IIterationLis...
method RecursiveIterationList (line 86) | protected void RecursiveIterationList(in IIterationList iterationList,...
method RecursiveIterationEventRoot (line 99) | protected void RecursiveIterationEventRoot(in IterationEventRoot itera...
method RecursiveEventData (line 149) | protected void RecursiveEventData(in EventData ed, in IterationEventRo...
method RecursiveEventDataWalker (line 249) | protected void RecursiveEventDataWalker(in EventData ed, in IterationE...
method TimeDisplay (line 262) | protected static string TimeDisplay(int depth, double time)
method PercentageDisplay (line 267) | protected static string PercentageDisplay(int depth, double percentage)
method SimpleLabel (line 272) | protected static string SimpleLabel(int depth, string s, string style ...
method AggregateEventData (line 282) | protected void AggregateEventData(EventData ed, double percentage, ref...
method AggregateData (line 298) | protected void AggregateData(string name, double time)
method AggregateDataToString (line 309) | protected string AggregateDataToString()
method FindAggregator (line 321) | protected HTMLAggregator FindAggregator(string name)
method AggregatorLabel (line 326) | protected static StringBuilder AggregatorLabel(HTMLAggregator ag)
method ToString (line 354) | public override string ToString()
FILE: Editor/Formatters/Reporters/HTMLReporter.cs
class HTMLReporter (line 9) | sealed class HTMLReporter : FileReporter
method GetPrefixStringBuilder (line 19) | protected override StringBuilder GetPrefixStringBuilder(in IIterationL...
method GetMainStringBuilder (line 40) | protected override StringBuilder GetMainStringBuilder(in IIterationLis...
method RecursiveIterationList (line 56) | void RecursiveIterationList(in IIterationList iterationList, ref Strin...
method RecursiveIterationEventRoot (line 69) | void RecursiveIterationEventRoot(in IterationEventRoot iterationEventR...
method RecursiveEventData (line 102) | void RecursiveEventData(in EventData ed, in IterationEventRoot parent,...
method RecursiveEventDataWalker (line 146) | void RecursiveEventDataWalker(in EventData ed, in IterationEventRoot i...
method TimeDisplay (line 159) | string TimeDisplay(int depth, double time)
method PercentageDisplay (line 164) | string PercentageDisplay(int depth, double percentage)
method SimpleLabel (line 169) | string SimpleLabel(int depth, string s, string style = "")
method ToString (line 179) | public override string ToString()
FILE: Editor/Formatters/Reporters/PlaintextReporter.cs
class PlaintextReporter (line 3) | public sealed class PlaintextReporter : FileReporter
method Report (line 13) | public override void Report(in IIterationList iterationList, string path)
method ToString (line 18) | public override string ToString()
FILE: Editor/IterationEventKind.cs
type IterationEventKind (line 5) | public enum IterationEventKind
FILE: Editor/IterationEventRoot.cs
class IterationEventRoot (line 8) | [Serializable]
method IterationEventRoot (line 43) | public IterationEventRoot(int index)
method IterationEventRoot (line 49) | public IterationEventRoot(int index, IterationEventKind eventKind)
method Reload (line 55) | public void Reload()
method StartEvent (line 73) | public EventData StartEvent(IterationEventKind kind, string identifier...
method StartEvent (line 84) | public EventData StartEvent(IterationEventKind kind)
method FinishEvent (line 89) | public void FinishEvent(string identifier)
method FinishEvent (line 95) | public void FinishEvent(IterationEventKind kind)
method AddChildEvent (line 101) | public EventData AddChildEvent(string identifier, string metadata, dou...
method SetParent (line 113) | public static void SetParent(EventData child, EventData parent)
method SetParent (line 129) | public void SetParent(EventData child, IterationEventKind kind)
method FindLastEvent (line 135) | public EventData FindLastEvent(IterationEventKind kind)
method FindLastEvent (line 141) | public EventData FindLastEvent(string identifier)
FILE: Editor/IterationList.cs
class IterationList (line 8) | [Serializable]
method IterationList (line 24) | public IterationList()
method NewIteration (line 30) | public void NewIteration(IterationEventKind kind)
method Clear (line 37) | public void Clear()
method Reload (line 45) | public void Reload()
method NotifyUpdated (line 55) | public void NotifyUpdated()
FILE: Editor/ProfilerDataCollector.cs
class ProfilerDataCollector (line 13) | [Serializable]
method ProfilerDataCollector (line 26) | public ProfilerDataCollector(IIterationList iterationList)
method Initialize (line 71) | void Initialize(IIterationList iterationList)
method Clear (line 76) | public void Clear()
method Subscribe (line 81) | public void Subscribe()
method Unsubscribe (line 86) | public void Unsubscribe()
method AddKeyMarkers (line 91) | static void AddKeyMarkers(IterationEventKind iterationEventKind, param...
method GetKeyMarkers (line 96) | static string[] GetKeyMarkers(IterationEventKind iterationEventKind)
method AddMarkerFlags (line 111) | static void AddMarkerFlags(string marker, EventDataFlags flags)
method AddThreadMarker (line 116) | static void AddThreadMarker(string marker, params string[] threadNames)
method Collect (line 121) | public void Collect(IterationEventKind iterationEventKind, IterationEv...
method ProfilerNewFrame (line 138) | void ProfilerNewFrame(int connectionId, int newFrameIndex)
method ReadProfilingData (line 240) | internal static void ReadProfilingData(IterationEventRoot iterationEve...
method FindMarkersInFrameData (line 306) | static bool FindMarkersInFrameData(HierarchyFrameDataView frameData, i...
class FrameSearchData (line 358) | [Serializable]
type MarkerData (line 367) | struct MarkerData
method MarkerData (line 374) | public MarkerData(int length)
FILE: Editor/UnityEditorEvents.cs
class UnityEditorEvents (line 7) | static class UnityEditorEvents
type Event (line 9) | public enum Event
method Subscribe (line 26) | public static void Subscribe()
method Unsubscribe (line 39) | public static void Unsubscribe()
method ScriptCompilationStarted (line 52) | static void ScriptCompilationStarted(object obj)
method ScriptCompilationFinished (line 57) | static void ScriptCompilationFinished(object obj)
method AssemblyCompilationStarted (line 62) | static void AssemblyCompilationStarted(string assembly)
method AssemblyCompilationFinished (line 67) | static void AssemblyCompilationFinished(string assembly, CompilerMessa...
method AssemblyReloadStarted (line 72) | static void AssemblyReloadStarted()
method AssemblyReloadFinished (line 77) | static void AssemblyReloadFinished()
method PlayModeStateChanged (line 82) | static void PlayModeStateChanged(PlayModeStateChange state)
FILE: Editor/UnityProfiling.cs
class UnityProfiling (line 7) | static class UnityProfiling
method SetProfileDeepScripts (line 20) | public static void SetProfileDeepScripts(bool deep)
method GetFrame (line 59) | public static HierarchyFrameDataView GetFrame(int frameIndex, int thre...
method GetFrame (line 66) | public static HierarchyFrameDataView GetFrame(int frameIndex, string t...
Condensed preview — 83 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (163K chars).
[
{
"path": ".gitignore",
"chars": 729,
"preview": "# =============== #\n# Unity generated #\n# =============== #\n[Ll]ibrary/\n[Tt]emp/\n[Oo]bj/\n[Bb]uild/\n[Bb]uilds/\n[Uu]nity[P"
},
{
"path": "CHANGELOG.md",
"chars": 652,
"preview": "# Changelog\nAll notable changes to the webrtc package will be documented in this file.\n\nThe format is based on [Keep a C"
},
{
"path": "CHANGELOG.md.meta",
"chars": 158,
"preview": "fileFormatVersion: 2\nguid: 249ab3ebb372f234e98dbac31f5e3265\nTextScriptImporter:\n externalObjects: {}\n userData: \n ass"
},
{
"path": "CONTRIBUTING.md",
"chars": 478,
"preview": "# Contributing\n\n## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/li"
},
{
"path": "CONTRIBUTING.md.meta",
"chars": 158,
"preview": "fileFormatVersion: 2\nguid: 2b6a7b8e81611044a8d28e71c0e71043\nTextScriptImporter:\n externalObjects: {}\n userData: \n ass"
},
{
"path": "Documentation~/TableOfContents.md",
"chars": 158,
"preview": "* [About the Editor Iteration Profiler](index.md)\n* [Using the Editor Iteration Profiler](editor-iteration-profiler.md)\n"
},
{
"path": "Documentation~/editor-iteration-profiler.md",
"chars": 1979,
"preview": "# Using the Editor Iteration Profiler\nOnce you’ve installed the Editor Iteration Profiler, navigate to __Window > Ana"
},
{
"path": "Documentation~/exporting-data.md",
"chars": 4260,
"preview": "# Exporting Data\n\nYou can export the data that the Editor Iteration Profiler captures in several different file formats "
},
{
"path": "Documentation~/index.md",
"chars": 2791,
"preview": "# About Editor Iteration Profiler\nThe Editor Iteration Profiler (EIP) is a tool that you can use alongside [Unity's buil"
},
{
"path": "Editor/DataCollector.cs",
"chars": 5777,
"preview": "using System;\nusing UnityEditor.EditorIterationProfiler.API;\nusing UnityEngine.Assertions;\n\nnamespace UnityEditor.Editor"
},
{
"path": "Editor/DataCollector.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: ea639bdc1b7738841a40c85658e414f1\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IEditorIterationProfilerController.cs",
"chars": 288,
"preview": "namespace UnityEditor.EditorIterationProfiler.API\n{\n public interface IEditorIterationProfilerController\n {\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IEditorIterationProfilerController.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 3b753f26d3c16a64fb73f79a76bfc62c\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IEventSubscriber.cs",
"chars": 155,
"preview": "namespace UnityEditor.EditorIterationProfiler\n{\n public interface IEventSubscriber\n {\n void Subscribe();\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IEventSubscriber.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: dfbe793476c38d545acebf95bef144a9\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IIterationList.cs",
"chars": 520,
"preview": "using System;\nusing System.Collections.Generic;\nusing UnityEditor.EditorIterationProfiler.Formatting;\n\nnamespace UnityE"
},
{
"path": "Editor/EditorIterationProfiler.API/IIterationList.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: b3881855ff94b2a419205af6f42f003b\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IProfilerDataCollector.cs",
"chars": 273,
"preview": "namespace UnityEditor.EditorIterationProfiler.API\n{\n public interface IProfilerDataCollector : IEventSubscriber\n "
},
{
"path": "Editor/EditorIterationProfiler.API/IProfilerDataCollector.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: a368e7eb7b9059c429c7bb9837c8f3fa\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfiler.API.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 69bdb52499db5994ca64e22a6bc04cf5\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Editor/EditorIterationProfilerAnalytics.cs",
"chars": 3158,
"preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.Analytics;\n\nnamespace U"
},
{
"path": "Editor/EditorIterationProfilerAnalytics.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 5248670f7ba3f2c419bab949189a46bc\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfilerController.cs",
"chars": 2422,
"preview": "using System.Collections.Generic;\nusing UnityEditor.EditorIterationProfiler.API;\nusing UnityEngine;\nusing UnityEngine.A"
},
{
"path": "Editor/EditorIterationProfilerController.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: a7e1f201c78caea4ab211abb5ca49032\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfilerIntegration.cs",
"chars": 2141,
"preview": "using System.Linq;\nusing UnityEditor.EditorIterationProfiler.API;\nusing UnityEngine;\nusing Object = UnityEngine.Object;"
},
{
"path": "Editor/EditorIterationProfilerIntegration.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 9920ea31757240744bbf4d4b9c7f9f14\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfilerSettings.cs",
"chars": 2353,
"preview": "using System;\nusing System.Text;\nusing UnityEditor.Compilation;\nusing UnityEngine;\n\nnamespace UnityEditor.EditorIterati"
},
{
"path": "Editor/EditorIterationProfilerSettings.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 0635b7d495ef2fa4a97e5eb88021bacf\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfilerTreeView.cs",
"chars": 12969,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.IMGUI.Controls;\nusing UnityEngine;\n"
},
{
"path": "Editor/EditorIterationProfilerTreeView.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: e6651dd15ebe6e1478d78afed8ff3dee\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EditorIterationProfilerWindow.cs",
"chars": 24046,
"preview": "using System;\nusing System.IO;\nusing System.Reflection;\nusing UnityEditor.EditorIterationProfiler.Formatting;\nusing Uni"
},
{
"path": "Editor/EditorIterationProfilerWindow.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 906f7aecdbdac3e4ba9518ba48388df9\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/EventData.cs",
"chars": 3601,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing UnityEngine;\n\nnamesp"
},
{
"path": "Editor/EventData.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 7ffe19a10dc4360459985d005f84ceab\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Aggregator.cs",
"chars": 2127,
"preview": "using System;\nusing System.Text;\nusing System.Text.RegularExpressions;\nusing static System.Double;\n\nnamespace UnityEdit"
},
{
"path": "Editor/Formatters/Aggregator.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 25551dbb66e6c084ab84c7a8e6cfc2e2\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/DataReporterProvider.cs",
"chars": 4090,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEditor.EditorIterationProfiler.Formatting"
},
{
"path": "Editor/Formatters/DataReporterProvider.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: ff2c9a40c83aa784bb9b3ff6047ee281\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/DataReporters.cs",
"chars": 450,
"preview": "namespace UnityEditor.EditorIterationProfiler.Formatting\n{\n public interface IDataReporter\n {\n string GetF"
},
{
"path": "Editor/Formatters/DataReporters.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 81edb0b5aa41ccd48ad73a8a21e67758\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/FileReporter.cs",
"chars": 916,
"preview": "using System;\nusing System.IO;\nusing UnityEngine;\n\nnamespace UnityEditor.EditorIterationProfiler.Formatting\n{\n publi"
},
{
"path": "Editor/Formatters/FileReporter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 9d728ac882039e643be468b5db8f65b9\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Formatter.cs",
"chars": 3268,
"preview": "using System;\nusing System.Text;\nusing static System.FormattableString;\n\nnamespace UnityEditor.EditorIterationProfiler."
},
{
"path": "Editor/Formatters/Formatter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: ac320eeadb74a314986b94329a9f324b\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/IndentationProvider.cs",
"chars": 664,
"preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace UnityEditor.EditorIterationPr"
},
{
"path": "Editor/Formatters/IndentationProvider.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 3b0423ed7f3314147a6125b4bca1b837\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters/CSVReporter.cs",
"chars": 1821,
"preview": "using System.Text;\n\nnamespace UnityEditor.EditorIterationProfiler.Formatting\n{\n sealed class CSVReporter : FileRepor"
},
{
"path": "Editor/Formatters/Reporters/CSVReporter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 6b8bb4034b7400549b745b3ae7c02f4c\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters/ChromeTracingReporter.cs",
"chars": 5092,
"preview": "using System;\nusing System.Text;\nusing static System.FormattableString;\n\nnamespace UnityEditor.EditorIterationProfiler."
},
{
"path": "Editor/Formatters/Reporters/ChromeTracingReporter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 72b0e40bb4a14f3478fcab6254a33ddf\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters/EditorLogReporter.cs",
"chars": 1927,
"preview": "using System.Text;\nusing UnityEngine;\n\nnamespace UnityEditor.EditorIterationProfiler.Formatting\n{\n public class Edit"
},
{
"path": "Editor/Formatters/Reporters/EditorLogReporter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 5699fdd33406e234598169fc247e67e6\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters/HTMLPerfReport.cs",
"chars": 14418,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Text.RegularExpressi"
},
{
"path": "Editor/Formatters/Reporters/HTMLPerfReport.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 5982d768475803a4185fccf2a6ac8642\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters/HTMLReporter.cs",
"chars": 6679,
"preview": "using System.Text;\nusing UnityEditor.EditorIterationProfiler.Formatting;\nusing System.IO;\nusing System.Linq;\nusing Unit"
},
{
"path": "Editor/Formatters/Reporters/HTMLReporter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: e616717ebe9a5aa41a86a75e07d38c16\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters/HTMLReporterPrefix.txt",
"chars": 1954,
"preview": "<html>\n<head>\n<style>\nbody {\n\tfont-family: monospace;\n}\nbody > .TreeViewItem {\n\tmargin-left: 175px;\n\tborder: none;\n}\n.W"
},
{
"path": "Editor/Formatters/Reporters/HTMLReporterPrefix.txt.meta",
"chars": 158,
"preview": "fileFormatVersion: 2\nguid: fa0a687d251c5484281dc568e5a0e2ad\nTextScriptImporter:\n externalObjects: {}\n userData: \n ass"
},
{
"path": "Editor/Formatters/Reporters/PlaintextReporter.cs",
"chars": 634,
"preview": "namespace UnityEditor.EditorIterationProfiler.Formatting\n{\n public sealed class PlaintextReporter : FileReporter\n "
},
{
"path": "Editor/Formatters/Reporters/PlaintextReporter.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 843fc8e922ce90b4fb75e591fe507647\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Formatters/Reporters.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: dded3bae191a0ba46be87613decab5af\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Editor/Formatters.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 313fa6debd8d20c46ad511bfbb6b4213\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "Editor/IterationEventKind.cs",
"chars": 371,
"preview": "using System;\n\nnamespace UnityEditor.EditorIterationProfiler\n{\n public enum IterationEventKind\n {\n None = "
},
{
"path": "Editor/IterationEventKind.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: c0ea77b406086944dbb826a1c0895a29\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/IterationEventRoot.cs",
"chars": 4652,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor.EditorIter"
},
{
"path": "Editor/IterationEventRoot.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 6efa6c94e301cfc4da89c7584f3ceb2a\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/IterationList.cs",
"chars": 1723,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace UnityEditor.EditorIter"
},
{
"path": "Editor/IterationList.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 685ab7a1693ff6d4588b129ce76cef56\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/ProfilerDataCollector.cs",
"chars": 14308,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEditor.EditorIteration"
},
{
"path": "Editor/ProfilerDataCollector.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: d1e3dc04d1e8e8344a237bfc5e3b756b\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/Unity.EditorIterationProfiler.Editor.asmdef",
"chars": 366,
"preview": "{\n \"name\": \"Unity.EditorIterationProfiler.Editor\",\n \"references\": [],\n \"includePlatforms\": [\n \"Editor\"\n "
},
{
"path": "Editor/Unity.EditorIterationProfiler.Editor.asmdef.meta",
"chars": 166,
"preview": "fileFormatVersion: 2\nguid: 00680d720d027674dbb1d8c51e1aaa52\nAssemblyDefinitionImporter:\n externalObjects: {}\n userData"
},
{
"path": "Editor/UnityEditorEvents.cs",
"chars": 3792,
"preview": "using System;\nusing System.IO;\nusing UnityEditor.Compilation;\n\nnamespace UnityEditor.EditorIterationProfiler\n{\n stat"
},
{
"path": "Editor/UnityEditorEvents.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: 521d993316e2dc54f9f64b52fe96eadf\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor/UnityProfiling.cs",
"chars": 3475,
"preview": "using System;\nusing UnityEditor.Profiling;\nusing UnityEditorInternal;\n\nnamespace UnityEditor.EditorIterationProfiler\n{\n"
},
{
"path": "Editor/UnityProfiling.cs.meta",
"chars": 243,
"preview": "fileFormatVersion: 2\nguid: dc5baee3fb0bc9f41ba836bff674eb06\nMonoImporter:\n externalObjects: {}\n serializedVersion: 2\n "
},
{
"path": "Editor.meta",
"chars": 172,
"preview": "fileFormatVersion: 2\nguid: 9949f7c4ae59ee7499a083d831233f16\nfolderAsset: yes\nDefaultImporter:\n externalObjects: {}\n us"
},
{
"path": "LICENSE.md",
"chars": 476,
"preview": "Editor Iteration Profiler copyright © 2020 Unity Technologies ApS\n\nLicensed under the Unity Companion License for Unity-"
},
{
"path": "LICENSE.md.meta",
"chars": 158,
"preview": "fileFormatVersion: 2\nguid: 0515e52add3ab464880c7466bcf136b8\nTextScriptImporter:\n externalObjects: {}\n userData: \n ass"
},
{
"path": "README.md",
"chars": 295,
"preview": "# Editor Iteration Profiler\nAssists in capturing frames from the Profiler of Domain Reloads in the Unity Editor. Compati"
},
{
"path": "README.md.meta",
"chars": 158,
"preview": "fileFormatVersion: 2\nguid: 41ae1fb9d1a93684bb23091b2c54ad2b\nTextScriptImporter:\n externalObjects: {}\n userData: \n ass"
},
{
"path": "package.json",
"chars": 571,
"preview": "{\n\t\"name\": \"com.unity.editoriterationprofiler\",\n\t\"displayName\":\"Editor Iteration Profiler\",\n\t\"version\": \"0.1.2-preview\","
},
{
"path": "package.json.meta",
"chars": 163,
"preview": "fileFormatVersion: 2\nguid: 9d114ba67f600c34994534b2b6994a8a\nPackageManifestImporter:\n externalObjects: {}\n userData: \n"
}
]
About this extraction
This page contains the full source code of the Unity-Technologies/com.unity.editoriterationprofiler GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 83 files (148.4 KB), approximately 33.5k tokens, and a symbol index with 242 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.