Skip to content

Commit

Permalink
feat: feature to send strings as index
Browse files Browse the repository at this point in the history
will save bandwidth when sending many strings that are the same
  • Loading branch information
James-Frowen committed Jun 7, 2024
1 parent c2785d1 commit 996d75b
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 3 deletions.
1 change: 1 addition & 0 deletions Assets/Mirage/Runtime/Serialization/NetworkReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Mirage.Serialization
/// </summary>
public unsafe class NetworkReader : IDisposable
{
public StringStore StringStore;
private byte[] _managedBuffer;
private GCHandle _handle;
private ulong* _longPtr;
Expand Down
4 changes: 3 additions & 1 deletion Assets/Mirage/Runtime/Serialization/NetworkWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ namespace Mirage.Serialization
/// </summary>
public unsafe class NetworkWriter
{
public StringStore StringStore;

/// <summary>
/// Max buffer size = 0.5MB
/// </summary>
private const int MAX_BUFFER_SIZE = 524_288;
private byte[] _managedBuffer;
private int _bitCapacity;

/// <summary>Allow internal buffer to resize if capcity is reached</summary>
/// <summary>Allow internal buffer to resize if capacity is reached</summary>
private readonly bool _allowResize;
private GCHandle _handle;
private ulong* _longPtr;
Expand Down
84 changes: 82 additions & 2 deletions Assets/Mirage/Runtime/Serialization/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

Expand Down Expand Up @@ -31,11 +32,29 @@ public static int MaxStringLength
private static byte[] stringBuffer = new byte[MaxStringLength];

/// <param name="value">string or null</param>
public static void WriteString(this NetworkWriter writer, string value) => WriteString(writer, value, defaultEncoding);
public static void WriteString(this NetworkWriter writer, string value)
{
// note, only use StringStore for default encoding
if (writer.StringStore != null)
{
writer.StringStore.WriteString(writer, value);
return;
}

WriteString(writer, value, defaultEncoding);
}

/// <returns>string or null</returns>
/// <exception cref="ArgumentException">Throws if invalid utf8 string is received</exception>
public static string ReadString(this NetworkReader reader) => ReadString(reader, defaultEncoding);
public static string ReadString(this NetworkReader reader)
{
if (reader.StringStore != null)
{
return reader.StringStore.ReadString(reader);
}

return ReadString(reader, defaultEncoding);
}

/// <param name="encoding">Use this for encoding other than the default (UTF8). Make sure to use same encoding for ReadString</param>
/// <param name="value">string or null</param>
Expand Down Expand Up @@ -90,5 +109,66 @@ public static string ReadString(this NetworkReader reader, Encoding encoding)
// convert directly from buffer to string via encoding
return encoding.GetString(data.Array, data.Offset, data.Count);
}
public static void WriteStringStore(this NetworkWriter writer, StringStore store)
{
var count = (uint)store.Strings.Count;
writer.WritePackedUInt32(count);
for (var i = 0; i < count; i++)
// use defaultEncoding, so we use the real write method and not the one that uses StringStore
writer.WriteString(store.Strings[i], defaultEncoding);
}
public static StringStore ReadStringStore(this NetworkReader reader)
{
var store = new StringStore();
var list = store.Strings;
var count = reader.ReadPackedUInt32();
for (var i = 0; i < count; i++)
list.Add(reader.ReadString(defaultEncoding));
return store;
}
}

public class StringStore
{
public Dictionary<string, int> Lookup = new Dictionary<string, int>();
public List<string> Strings = new List<string>();

public int GetKey(string value)
{
if (Lookup.TryGetValue(value, out var index))
{
return index;
}
else
{
index = Strings.Count;
Strings.Add(value);
Lookup.Add(value, index);
return index;
}
}

public void WriteString(NetworkWriter writer, string value)
{
if (value == null)
{
writer.WritePackedUInt32(0);
}
else
{
var key = GetKey(value);
writer.WritePackedUInt32(checked((uint)(key + 1)));
}
}

public string ReadString(NetworkReader reader)
{
var key = reader.ReadPackedUInt32();
if (key == 0)
return null;

var index = checked((int)(key - 1));
return Strings[index];
}
}
}

0 comments on commit 996d75b

Please sign in to comment.