From f653f107501cb5b757705385902bf48cb5f52e77 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 30 Jul 2026 13:25:13 +0900 Subject: [PATCH] Improving the performance degradation caused by Span generation --- .../Runtime/UniJSON/Json/JsonParser.cs | 14 +++-- .../UniJSON/Utf8String/Utf8Iterator.cs | 32 ++++------ .../Runtime/UniJSON/Utf8String/Utf8String.cs | 60 ++++--------------- .../Utf8String/Utf8StringExtensions.cs | 13 ++-- 4 files changed, 41 insertions(+), 78 deletions(-) diff --git a/Packages/UniGLTF/Runtime/UniJSON/Json/JsonParser.cs b/Packages/UniGLTF/Runtime/UniJSON/Json/JsonParser.cs index 21a2c2e73..60dc2ad9c 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Json/JsonParser.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Json/JsonParser.cs @@ -66,14 +66,16 @@ namespace UniJSON /// static JsonNode ParsePrimitive(JsonNode tree, Utf8String segment, ValueNodeType valueType) { + var span = segment.Bytes.Span; int i = 1; - for (; i < segment.ByteLength; ++i) + for (; i < span.Length; ++i) { - if (Char.IsWhiteSpace((char)segment[i]) - || segment[i] == '}' - || segment[i] == ']' - || segment[i] == ',' - || segment[i] == ':' + var b = span[i]; + if (Char.IsWhiteSpace((char)b) + || b == '}' + || b == ']' + || b == ',' + || b == ':' ) { break; diff --git a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8Iterator.cs b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8Iterator.cs index 9dbc22bb8..686475401 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8Iterator.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8Iterator.cs @@ -1,19 +1,22 @@ using System; -using System.Collections; -using System.Collections.Generic; namespace UniJSON { - public struct Utf8Iterator : IEnumerator + public ref struct Utf8Iterator { - ReadOnlyMemory m_memory; + ReadOnlySpan m_span; int m_start; int m_position; public Utf8Iterator(ReadOnlyMemory memory, int start = 0) + : this(memory.Span, start) { - m_memory = memory; + } + + public Utf8Iterator(ReadOnlySpan span, int start = 0) + { + m_span = span; m_start = start; m_position = -1; } @@ -53,27 +56,22 @@ namespace UniJSON public byte Current { - get { return m_memory.Span[m_position]; } - } - - object IEnumerator.Current - { - get { return Current; } + get { return m_span[m_position]; } } public byte Second { - get { return m_memory.Span[m_position + 1]; } + get { return m_span[m_position + 1]; } } public byte Third { - get { return m_memory.Span[m_position + 2]; } + get { return m_span[m_position + 2]; } } public byte Fourth { - get { return m_memory.Span[m_position + 3]; } + get { return m_span[m_position + 3]; } } public const uint Mask1 = 0x01; @@ -170,10 +168,6 @@ namespace UniJSON } } - public void Dispose() - { - } - public bool MoveNext() { if (m_position == -1) @@ -184,7 +178,7 @@ namespace UniJSON { m_position += CurrentByteLength; } - return m_position < m_memory.Length; + return m_position < m_span.Length; } public void Reset() diff --git a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs index 9a6a70802..fdf9f179e 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs @@ -139,38 +139,12 @@ namespace UniJSON public bool StartsWith(Utf8String rhs) { - if (rhs.ByteLength > ByteLength) - { - return false; - } - - for (int i = 0; i < rhs.ByteLength; ++i) - { - if (this[i] != rhs[i]) - { - return false; - } - } - - return true; + return Bytes.Span.StartsWith(rhs.Bytes.Span); } public bool EndsWith(Utf8String rhs) { - if (rhs.ByteLength > ByteLength) - { - return false; - } - - for (int i = 1; i <= rhs.ByteLength; ++i) - { - if (this[ByteLength - i] != rhs[rhs.ByteLength - i]) - { - return false; - } - } - - return true; + return Bytes.Span.EndsWith(rhs.Bytes.Span); } public int IndexOf(Byte code) @@ -219,10 +193,11 @@ namespace UniJSON public Utf8String TrimStart() { + var span = Bytes.Span; var i = 0; - for (; i < ByteLength; ++i) + for (; i < span.Length; ++i) { - if (!IsSpace(this[i])) + if (!IsSpace(span[i])) { break; } @@ -232,10 +207,11 @@ namespace UniJSON public Utf8String TrimEnd() { - var i = ByteLength-1; + var span = Bytes.Span; + var i = span.Length - 1; for (; i >= 0; --i) { - if (!IsSpace(this[i])) + if (!IsSpace(span[i])) { break; } @@ -265,20 +241,7 @@ namespace UniJSON public bool Equals(Utf8String other) { - if (ByteLength != other.ByteLength) - { - return false; - } - - for (int i = 0; i < ByteLength; ++i) - { - if (this[i] != other[i]) - { - return false; - } - } - - return true; + return Bytes.Span.SequenceEqual(other.Bytes.Span); } public override int GetHashCode() @@ -296,9 +259,10 @@ namespace UniJSON get { //bool isInt = false; - for (int i = 0; i < ByteLength; ++i) + var span = Bytes.Span; + for (int i = 0; i < span.Length; ++i) { - var c = this[i]; + var c = span[i]; if (c == '0' || c == '1' || c == '2' diff --git a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs index c9530bd1c..f2b7cab4e 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs @@ -23,10 +23,11 @@ namespace UniJSON public static bool TrySearchByte(this Utf8String src, Func pred, out int pos) { + var span = src.Bytes.Span; pos = 0; - for (; pos < src.ByteLength; ++pos) + for (; pos < span.Length; ++pos) { - if (pred(src[pos])) + if (pred(span[pos])) { return true; } @@ -88,6 +89,7 @@ namespace UniJSON public static IEnumerable Split(this Utf8String src, byte delimiter) { + var results = new List(); var start = 0; var p = new Utf8Iterator(src.Bytes); while (p.MoveNext()) @@ -96,11 +98,11 @@ namespace UniJSON { if (p.BytePosition - start == 0) { - yield return default(Utf8String); + results.Add(default(Utf8String)); } else { - yield return src.Subbytes(start, p.BytePosition - start); + results.Add(src.Subbytes(start, p.BytePosition - start)); } start = p.BytePosition + 1; } @@ -108,8 +110,9 @@ namespace UniJSON if (start < p.BytePosition) { - yield return src.Subbytes(start, p.BytePosition - start); + results.Add(src.Subbytes(start, p.BytePosition - start)); } + return results; } #region atoi