Skip to content

Commit 2a28a24

Browse files
==
authored andcommitted
[jacksondunstan#51] Fix performance issue with Object Store
When BaseMaxSimultaneous was set to a large number the object-store was spending to much time finding the handle. This was fixed using a dictionary where the keys have the objects full hash.
1 parent b508933 commit 2a28a24

1 file changed

Lines changed: 20 additions & 65 deletions

File tree

Unity/Assets/NativeScript/Bindings.cs

Lines changed: 20 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections;
55
using System.IO;
66
using System.Runtime.InteropServices;
7+
using System.Collections.Generic;
78

89
using UnityEngine;
910

@@ -24,19 +25,13 @@ public static class Bindings
2425
// Holds objects and provides handles to them in the form of ints
2526
public static class ObjectStore
2627
{
28+
static Dictionary<uint, int> handleLookupByHash;
29+
static Dictionary<int, uint> hashLookupByHandle;
30+
static Stack<int> freeHandleStack;
31+
2732
// Stored objects. The first is never used so 0 can be "null".
2833
static object[] objects;
2934

30-
// Stack of available handles
31-
static int[] handles;
32-
33-
// Hash table of stored objects to their handles.
34-
static object[] keys;
35-
static int[] values;
36-
37-
// Index of the next available handle
38-
static int nextHandleIndex;
39-
4035
// The maximum number of objects to store. Must be positive.
4136
static int maxObjects;
4237

@@ -49,19 +44,13 @@ public static void Init(int maxObjects)
4944
objects = new object[maxObjects + 1];
5045

5146
// Initialize the handles stack as 1, 2, 3, ...
52-
handles = new int[maxObjects];
5347
for (
5448
int i = 0, handle = maxObjects;
5549
i < maxObjects;
5650
++i, --handle)
5751
{
58-
handles[i] = handle;
52+
freeHandleStack.Push(handle);
5953
}
60-
nextHandleIndex = maxObjects - 1;
61-
62-
// Initialize the hash table
63-
keys = new object[maxObjects];
64-
values = new int[maxObjects];
6554
}
6655

6756
public static int Store(object obj)
@@ -75,27 +64,15 @@ public static int Store(object obj)
7564
lock (objects)
7665
{
7766
// Pop a handle off the stack
78-
int handle = handles[nextHandleIndex];
79-
nextHandleIndex--;
67+
int handle = freeHandleStack.Pop();
8068

8169
// Store the object
8270
objects[handle] = obj;
8371

8472
// Insert into the hash table
85-
int initialIndex = (int)(
86-
((uint)obj.GetHashCode()) % maxObjects);
87-
int index = initialIndex;
88-
do
89-
{
90-
if (object.ReferenceEquals(keys[index], null))
91-
{
92-
keys[index] = obj;
93-
values[index] = handle;
94-
break;
95-
}
96-
index = (index + 1) % maxObjects;
97-
}
98-
while (index != initialIndex);
73+
uint hash = (uint)obj.GetHashCode();
74+
handleLookupByHash.Add(hash, handle);
75+
hashLookupByHandle.Add(handle, hash);
9976

10077
return handle;
10178
}
@@ -108,6 +85,7 @@ public static object Get(int handle)
10885

10986
public static int GetHandle(object obj)
11087
{
88+
11189
// Null is always zero
11290
if (object.ReferenceEquals(obj, null))
11391
{
@@ -116,19 +94,12 @@ public static int GetHandle(object obj)
11694

11795
lock (objects)
11896
{
119-
// Look up the object in the hash table
120-
int initialIndex = (int)(
121-
((uint)obj.GetHashCode()) % maxObjects);
122-
int index = initialIndex;
123-
do
97+
// Look up the handle in the hash table
98+
uint hash = (uint)obj.GetHashCode();
99+
if (handleLookupByHash.ContainsKey(hash))
124100
{
125-
if (object.ReferenceEquals(keys[index], obj))
126-
{
127-
return values[index];
128-
}
129-
index = (index + 1) % maxObjects;
101+
return handleLookupByHash[hash];
130102
}
131-
while (index != initialIndex);
132103
}
133104

134105
// Object not found
@@ -150,28 +121,12 @@ public static object Remove(int handle)
150121
objects[handle] = null;
151122

152123
// Push the handle onto the stack
153-
nextHandleIndex++;
154-
handles[nextHandleIndex] = handle;
124+
freeHandleStack.Push(handle);
155125

156-
// Remove the object from the hash table
157-
int initialIndex = (int)(
158-
((uint)obj.GetHashCode()) % maxObjects);
159-
int index = initialIndex;
160-
do
161-
{
162-
if (object.ReferenceEquals(keys[index], obj))
163-
{
164-
// Only the key needs to be removed (set to null)
165-
// because values corresponding to null will never
166-
// be read and the values are just integers, so
167-
// we're not holding on to a managed reference that
168-
// will prevent GC.
169-
keys[index] = null;
170-
break;
171-
}
172-
index = (index + 1) % maxObjects;
173-
}
174-
while (index != initialIndex);
126+
// Remove the object from the hash dictionary's
127+
var hash = hashLookupByHandle[handle];
128+
handleLookupByHash.Remove(hash);
129+
hashLookupByHandle.Remove(handle);
175130

176131
return obj;
177132
}

0 commit comments

Comments
 (0)