Browse Source

Optimize: LuaTable.TryGetNext

Akeit0 11 months ago
parent
commit
e0dd90a48d
2 changed files with 30 additions and 16 deletions
  1. 28 4
      src/Lua/Internal/LuaValueDictionary.cs
  2. 2 12
      src/Lua/LuaTable.cs

+ 28 - 4
src/Lua/Internal/LuaValueDictionary.cs

@@ -45,7 +45,7 @@ namespace Lua.Internal
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             get
             {
             {
-                ref LuaValue value = ref FindValue(key);
+                ref LuaValue value = ref FindValue(key, out _);
                 if (!Unsafe.IsNullRef(ref value))
                 if (!Unsafe.IsNullRef(ref value))
                 {
                 {
                     return value;
                     return value;
@@ -77,7 +77,7 @@ namespace Lua.Internal
         }
         }
 
 
         public bool ContainsKey(LuaValue key) =>
         public bool ContainsKey(LuaValue key) =>
-            !Unsafe.IsNullRef(ref FindValue(key));
+            !Unsafe.IsNullRef(ref FindValue(key, out _));
 
 
         public bool ContainsValue(LuaValue value)
         public bool ContainsValue(LuaValue value)
         {
         {
@@ -97,8 +97,9 @@ namespace Lua.Internal
 
 
         public Enumerator GetEnumerator() => new Enumerator(this);
         public Enumerator GetEnumerator() => new Enumerator(this);
 
 
-        internal ref LuaValue FindValue(LuaValue key)
+        internal ref LuaValue FindValue(LuaValue key, out int index)
         {
         {
+            index = -1;
             ref Entry entry = ref Unsafe.NullRef<Entry>();
             ref Entry entry = ref Unsafe.NullRef<Entry>();
             if (_buckets != null)
             if (_buckets != null)
             {
             {
@@ -123,6 +124,7 @@ namespace Lua.Internal
                         entry = ref entries[i];
                         entry = ref entries[i];
                         if (entry.hashCode == hashCode && entry.key.Equals(key))
                         if (entry.hashCode == hashCode && entry.key.Equals(key))
                         {
                         {
+                            index = i;
                             goto ReturnFound;
                             goto ReturnFound;
                         }
                         }
 
 
@@ -352,7 +354,7 @@ namespace Lua.Internal
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool TryGetValue(LuaValue key, out LuaValue value)
         public bool TryGetValue(LuaValue key, out LuaValue value)
         {
         {
-            ref LuaValue valRef = ref FindValue(key);
+            ref LuaValue valRef = ref FindValue(key, out _);
             if (!Unsafe.IsNullRef(ref valRef))
             if (!Unsafe.IsNullRef(ref valRef))
             {
             {
                 value = valRef;
                 value = valRef;
@@ -363,6 +365,27 @@ namespace Lua.Internal
             return false;
             return false;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryGetNext(LuaValue key, out KeyValuePair<LuaValue,LuaValue> pair)
+        {
+            ref LuaValue valRef = ref FindValue(key, out var index);
+            if (!Unsafe.IsNullRef(ref valRef))
+            {
+                Entry[] entries = _entries!;
+                while (++index  < _count)
+                {
+                    ref Entry entry = ref entries[index];
+                    if (entry is { next: >= -1, value.Type: not LuaValueType.Nil })
+                    {
+                        pair = new(entry.key, entry.value);
+                        return true;
+                    }
+                }
+            }
+
+            pair = default;
+            return false;
+        }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private ref int GetBucket(uint hashCode)
         private ref int GetBucket(uint hashCode)
@@ -428,6 +451,7 @@ namespace Lua.Internal
 
 
             public KeyValuePair<LuaValue, LuaValue> Current => _current;
             public KeyValuePair<LuaValue, LuaValue> Current => _current;
         }
         }
+
         static class ThrowHelper
         static class ThrowHelper
         {
         {
             public static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
             public static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()

+ 2 - 12
src/Lua/LuaTable.cs

@@ -194,19 +194,9 @@ public sealed class LuaTable
         }
         }
         else
         else
         {
         {
-            var foundKey = false;
-            foreach (var kv in dictionary)
+            if(dictionary.TryGetNext(key, out pair))
             {
             {
-                if (foundKey && kv.Value.Type is not LuaValueType.Nil)
-                {
-                    pair = kv;
-                    return true;
-                }
-
-                if (kv.Key.Equals(key))
-                {
-                    foundKey = true;
-                }
+                return true;
             }
             }
         }
         }