Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save noisecrime/a36059a7170811fab88603a9c0bbc8bc to your computer and use it in GitHub Desktop.
Save noisecrime/a36059a7170811fab88603a9c0bbc8bc to your computer and use it in GitHub Desktop.
Find out what assemblies are being built and how long each takes.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
namespace NoiseCrimeStudios.Editor.Settings
{
/// <summary>
/// Editor class that produces a report detailing what assemblies are recompiled and the time take.
/// Can be enabled/disabled in the Editor via Windows Menu item.
/// </summary>
/// <remarks>
/// Based on original code by Karl Jones https://gist.github.com/karljj1/9c6cce803096b5cd4511cf0819ff517b
/// Note: eWindowMenuItemPriorties is a custom Enum that defines priorty int values. Just replace it with an int value.
/// </remarks>
[InitializeOnLoad]
static class AssemblyCompilationReport
{
const string menuItemName = "Window/NoiseCrimeStudios/EditorSettings/AssemblyCompilationReport";
const string isEnabledEditorPref = "com.noisecrimestudios.AssemblyReport.Enabled";
const string assemblyReloadTimeEditorPref = "com.noisecrimestudios.AssemblyReport.ReloadEventsTime";
const string assemblyCompilationEventsEditorPref = "com.noisecrimestudios.AssemblyReport.CompilationEvents";
const string assemblyCompilationTimeEditorPref = "com.noisecrimestudios.AssemblyReport.TotalCompilationTime";
static readonly int scriptAssembliesPathLen = "Library/ScriptAssemblies/".Length;
static double s_CompilationTotalTime;
static bool s_EnabledState = false;
static StringBuilder s_BuildEvents = new StringBuilder();
static Dictionary<string, DateTime> s_StartTimes = new Dictionary<string, DateTime>();
static AssemblyCompilationReport()
{
// Use SetEnabledState to enable/disable at start up.
SetEnabledState( EditorPrefs.GetBool( isEnabledEditorPref, false ) );
}
static void CompilationPipelineOnAssemblyCompilationStarted( string assembly )
{
s_StartTimes[ assembly ] = DateTime.UtcNow;
}
static void CompilationPipelineOnAssemblyCompilationFinished( string assembly, CompilerMessage[] arg2 )
{
var timeSpan = DateTime.UtcNow - s_StartTimes[assembly];
s_CompilationTotalTime += timeSpan.TotalMilliseconds;
s_BuildEvents.AppendFormat( " {0:0.00}s {1}\n", timeSpan.TotalMilliseconds / 1000f, assembly.Substring( scriptAssembliesPathLen, assembly.Length - scriptAssembliesPathLen ) );
}
static void AssemblyReloadEventsOnBeforeAssemblyReload()
{
var totalCompilationTimeSeconds = s_CompilationTotalTime / 1000f;
s_BuildEvents.AppendFormat( "Assembly Compilation took {0:0.00} seconds\n", totalCompilationTimeSeconds );
EditorPrefs.SetString( assemblyReloadTimeEditorPref, DateTime.UtcNow.ToBinary().ToString() );
EditorPrefs.SetString( assemblyCompilationTimeEditorPref, totalCompilationTimeSeconds.ToString( CultureInfo.InvariantCulture ) );
EditorPrefs.SetString( assemblyCompilationEventsEditorPref, s_BuildEvents.ToString() );
}
static void AssemblyReloadEventsOnAfterAssemblyReload()
{
if ( !AllKeysPresent() )
{
Debug.Log( $"Assembly Compilation Report: Unable to report as editor prefs data is missing." );
return;
}
float compilationTotalTimeVal;
string compilationTotalTimeStr = EditorPrefs.GetString(assemblyCompilationTimeEditorPref);
if ( float.TryParse( compilationTotalTimeStr, out compilationTotalTimeVal ) )
{
long reloadTimeVal;
string reloadTimeStr = EditorPrefs.GetString(assemblyReloadTimeEditorPref);
if ( long.TryParse( reloadTimeStr, out reloadTimeVal ) )
{
var reloadDate = DateTime.FromBinary(reloadTimeVal);
var reloadTime = DateTime.UtcNow - reloadDate;
var compilationTimes = EditorPrefs.GetString(assemblyCompilationEventsEditorPref);
var totalTimeSeconds = compilationTotalTimeVal + reloadTime.TotalSeconds;
if ( !string.IsNullOrEmpty( compilationTimes ) )
Debug.Log( $"Assembly Compilation Report: Completed in {totalTimeSeconds:F2} seconds\n{compilationTimes}Assembly Reload took {reloadTime.TotalSeconds:F2} seconds\n" );
}
}
// Delete EditorPrefs that store results to keep things clean and lean.
DeleteEditorPrefKeys();
}
static bool AllKeysPresent()
{
if ( !EditorPrefs.HasKey(assemblyReloadTimeEditorPref) ) return false;
if ( !EditorPrefs.HasKey(assemblyCompilationTimeEditorPref ) ) return false;
if ( !EditorPrefs.HasKey(assemblyCompilationEventsEditorPref ) ) return false;
return true;
}
static void DeleteEditorPrefKeys()
{
EditorPrefs.DeleteKey( assemblyReloadTimeEditorPref );
EditorPrefs.DeleteKey( assemblyCompilationEventsEditorPref );
EditorPrefs.DeleteKey( assemblyCompilationTimeEditorPref );
}
#region Public Methods
public static void SetEnabledState( bool state )
{
// Set enabled State
s_EnabledState = state;
// Update editorPref with enabled state.
EditorPrefs.SetBool( isEnabledEditorPref, state );
if ( state )
{
CompilationPipeline.assemblyCompilationStarted += CompilationPipelineOnAssemblyCompilationStarted;
CompilationPipeline.assemblyCompilationFinished += CompilationPipelineOnAssemblyCompilationFinished;
AssemblyReloadEvents.beforeAssemblyReload += AssemblyReloadEventsOnBeforeAssemblyReload;
AssemblyReloadEvents.afterAssemblyReload += AssemblyReloadEventsOnAfterAssemblyReload;
}
else
{
CompilationPipeline.assemblyCompilationStarted -= CompilationPipelineOnAssemblyCompilationStarted;
CompilationPipeline.assemblyCompilationFinished -= CompilationPipelineOnAssemblyCompilationFinished;
AssemblyReloadEvents.beforeAssemblyReload -= AssemblyReloadEventsOnBeforeAssemblyReload;
AssemblyReloadEvents.afterAssemblyReload -= AssemblyReloadEventsOnAfterAssemblyReload;
}
}
#endregion
#region MenumItems
[MenuItem( menuItemName, false, ( int )eWindowMenuItemPriorties.EditorSettings + 15 )]
static void ToggleOption()
{
SetEnabledState( !s_EnabledState );
}
[MenuItem( menuItemName, true, ( int )eWindowMenuItemPriorties.EditorSettings + 15 )]
public static bool ValidateToggleOption()
{
Menu.SetChecked( menuItemName, s_EnabledState );
return true;
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment