Skip to content
This repository has been archived by the owner on Mar 6, 2018. It is now read-only.

Commit

Permalink
Optimize game startup by delaying constructor or calculation of some …
Browse files Browse the repository at this point in the history
…expensive things (#190)

Turns out these kinds of things were (relatively) expensive to do at startup:
- Construct the vertexes for DefaultGraphicsBlit; this is now done on first blit instead
- Obtain the GC metrics for the performance visualiser; this is now done in a background task
- Calculating mappings for the AOT network message serialization; this is now done on first use instead
  • Loading branch information
hach-que committed Jun 3, 2017
1 parent 4227697 commit 31f2591
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 26 deletions.
27 changes: 18 additions & 9 deletions Protogame/Graphics/DefaultGraphicsBlit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,8 @@ namespace Protogame
/// <interface_ref>Protogame.IGraphicsBlit</interface_ref>
public class DefaultGraphicsBlit : IGraphicsBlit
{
private readonly VertexPositionNormalTexture[] _vertexes =
{
new VertexPositionNormalTexture(new Vector3(0, 1, 0), Vector3.Zero, new Vector2(0, 1)),
new VertexPositionNormalTexture(new Vector3(0, 0, 0), Vector3.Zero, new Vector2(0, 0)),
new VertexPositionNormalTexture(new Vector3(1, 1, 0), Vector3.Zero, new Vector2(1, 1)),
new VertexPositionNormalTexture(new Vector3(1, 0, 0), Vector3.Zero, new Vector2(1, 0))
};

private readonly short[] _indicies = { 1, 3, 0, 2 };
private VertexPositionNormalTexture[] _vertexes;
private short[] _indicies;

private readonly IBackBufferDimensions _backBufferDimensions;
private readonly IAssetReference<UberEffectAsset> _blitEffect;
Expand Down Expand Up @@ -136,13 +129,29 @@ public class DefaultGraphicsBlit : IGraphicsBlit

if (_vertexBuffer == null)
{
if (_vertexes == null)
{
_vertexes = new[]
{
new VertexPositionNormalTexture(new Vector3(0, 1, 0), Vector3.Zero, new Vector2(0, 1)),
new VertexPositionNormalTexture(new Vector3(0, 0, 0), Vector3.Zero, new Vector2(0, 0)),
new VertexPositionNormalTexture(new Vector3(1, 1, 0), Vector3.Zero, new Vector2(1, 1)),
new VertexPositionNormalTexture(new Vector3(1, 0, 0), Vector3.Zero, new Vector2(1, 0))
};
}

_vertexBuffer = new VertexBuffer(renderContext.GraphicsDevice, typeof (VertexPositionNormalTexture),
_vertexes.Length, BufferUsage.WriteOnly);
_vertexBuffer.SetData(_vertexes);
}

if (_indexBuffer == null)
{
if (_indicies == null)
{
_indicies = new short[] { 1, 3, 0, 2 };
}

_indexBuffer = new IndexBuffer(renderContext.GraphicsDevice, typeof (short), _indicies.Length,
BufferUsage.WriteOnly);
_indexBuffer.SetData(_indicies);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,54 @@ namespace Protogame
{
public class AheadOfTimeNetworkMessageSerialization : INetworkMessageSerialization
{
private readonly INetworkMessage[] _networkMessages;

private Dictionary<string, Type> _stringToType;

private Dictionary<Type, string> _typeToString;

private Dictionary<Type, TypeModel> _typeToSerializer;

private bool _hasInited;

public AheadOfTimeNetworkMessageSerialization(INetworkMessage[] networkMessages)
{
var mapped = networkMessages.Select(x => x.GetType())
_networkMessages = networkMessages;
}

private void Init()
{
var mapped = _networkMessages.Select(x => x.GetType())
.Select(x => new
{
Type = x,
Attribute =
x.GetCustomAttributes(typeof (NetworkMessageAttribute), false).FirstOrDefault() as
x.GetCustomAttributes(typeof(NetworkMessageAttribute), false).FirstOrDefault() as
NetworkMessageAttribute
}).Where(x => x.Attribute != null).ToList();
_stringToType = mapped.ToDictionary(k => k.Attribute.MessageType, v => v.Type);
_typeToString = mapped.ToDictionary(k => k.Type, v => v.Attribute.MessageType);

var assembliesToSerializers = networkMessages.Select(x => x.GetType().Assembly).Distinct()
var assembliesToSerializers = _networkMessages.Select(x => x.GetType().Assembly).Distinct()
.ToDictionary(
k => k,
v => (TypeModel) Activator.CreateInstance(
v => (TypeModel)Activator.CreateInstance(
v.GetType("_NetworkSerializers.<>GeneratedSerializer")));
_typeToSerializer = networkMessages.Select(x => x.GetType())
_typeToSerializer = _networkMessages.Select(x => x.GetType())
.ToDictionary(
k => k,
v => assembliesToSerializers[v.Assembly]);

_hasInited = true;
}

public byte[] Serialize<T>(T message)
{
if (!_hasInited)
{
Init();
}

var serialized = InternalSerialize(message);
var type = _typeToString[typeof(T)];

Expand All @@ -54,6 +70,11 @@ public byte[] Serialize<T>(T message)

public byte[] Serialize(object message)
{
if (!_hasInited)
{
Init();
}

var serialized = InternalSerialize(message);
var type = _typeToString[message.GetType()];

Expand All @@ -67,6 +88,11 @@ public byte[] Serialize(object message)

public object Deserialize(byte[] message, out Type type)
{
if (!_hasInited)
{
Init();
}

var len = message[0];
var tlen = message.Length;
var typeBytes = new byte[len];
Expand All @@ -80,6 +106,11 @@ public object Deserialize(byte[] message, out Type type)

public object Deserialize(byte[] message)
{
if (!_hasInited)
{
Init();
}

Type discarded;
return Deserialize(message, out discarded);
}
Expand Down
30 changes: 18 additions & 12 deletions Protogame/Profiling/GCMetricsProfilerVisualiser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading;
#if PLATFORM_WINDOWS || PLATFORM_MACOS || PLATFORM_LINUX
using System.Diagnostics;
#endif
Expand All @@ -12,9 +13,9 @@ public class GCMetricsProfilerVisualiser : IGCMetricsProfilerVisualiser
private readonly IAssetReference<FontAsset> _defaultFont;

#if PLATFORM_WINDOWS || PLATFORM_MACOS || PLATFORM_LINUX
private readonly PerformanceCounter _gen0PerformanceCounter;
private readonly PerformanceCounter _gen1PerformanceCounter;
private readonly PerformanceCounter _gen2PerformanceCounter;
private PerformanceCounter _gen0PerformanceCounter;
private PerformanceCounter _gen1PerformanceCounter;
private PerformanceCounter _gen2PerformanceCounter;
#endif

private const string CategoryName = "Process";
Expand All @@ -32,16 +33,21 @@ public class GCMetricsProfilerVisualiser : IGCMetricsProfilerVisualiser
_defaultFont = assetManager.Get<FontAsset>("font.Default");

#if PLATFORM_WINDOWS || PLATFORM_MACOS || PLATFORM_LINUX
string instanceName;
if (TryGetInstanceName(Process.GetCurrentProcess(), out instanceName))
// TryGetInstanceName can take up to 1.5 seconds to complete! Queue the work of resolving
// these metrics on a background thread so we don't block game startup.
ThreadPool.QueueUserWorkItem(o =>
{
_gen0PerformanceCounter = new PerformanceCounter(".NET CLR Memory", "# Gen 0 Collections",
instanceName, true);
_gen1PerformanceCounter = new PerformanceCounter(".NET CLR Memory", "# Gen 1 Collections",
instanceName, true);
_gen2PerformanceCounter = new PerformanceCounter(".NET CLR Memory", "# Gen 2 Collections",
instanceName, true);
}
string instanceName;
if (TryGetInstanceName(Process.GetCurrentProcess(), out instanceName))
{
_gen0PerformanceCounter = new PerformanceCounter(".NET CLR Memory", "# Gen 0 Collections",
instanceName, true);
_gen1PerformanceCounter = new PerformanceCounter(".NET CLR Memory", "# Gen 1 Collections",
instanceName, true);
_gen2PerformanceCounter = new PerformanceCounter(".NET CLR Memory", "# Gen 2 Collections",
instanceName, true);
}
});
#endif
}

Expand Down

0 comments on commit 31f2591

Please sign in to comment.