@daneren2005/shared-memory-objects 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -2
- package/package.json +6 -2
- package/src/__tests__/memory-heap.spec.ts +0 -92
- package/src/__tests__/serialize-object.spec.ts +0 -23
- package/src/__tests__/shared-data.bench.ts +0 -166
- package/src/__tests__/shared-list.spec.ts +0 -247
- package/src/__tests__/shared-map.spec.ts +0 -98
- package/src/__tests__/shared-string.spec.ts +0 -75
- package/src/__tests__/shared-vector.spec.ts +0 -163
- package/src/utils/__tests__/pointer.spec.ts +0 -18
package/README.md
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
# Shared Memory Objects
|
|
2
|
-
A library to try to make making a multi-threaded game in Javascript possible.
|
|
2
|
+
A library to try to make making a multi-threaded game in Javascript possible. This package is to provide a wrapper to create objects and data structures that are backed by a SharedArrayBuffer and can be shared between multiple threads. The end result is a package that has all of the slowness of Javascript with all of the baggage of dealing with manual memory allocations. If you need to multi-thread you are probably better of just using a different language and compiling to WebAssembly. But if you, like me, just want to use Javascript/Typescript and are willing to deal with dealing with manual memory allocations then this library could save you some time.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
## Basics
|
|
5
|
+
The core of this package is the MemoryHeap. You should usually just have a single heap that is shared between all of your different threads. Each heap can have multiple MemoryBuffers. By default each buffer is only 8KB but it can be configured up to 1MB, and you can have up to 4k buffers for a total of 4GB. When you allocate memory, if there is not enough space it will allocate another buffers automatically. When allocating memory, you will get a AllocatedMemory object that is a wrapper around the allocated memory by calling `heap.allocUI32({count of 32 bit numbers})`. By default AllocatedMemory is backed by a Uint32Array but you can get any type of array from `AllocatedMemory.getArray(Int32Array);`.
|
|
6
|
+
|
|
7
|
+
Each allocated memory location can be stored as an int pointer. You can use `getPointer(int)` to get the bufferPosition (ie: buffer index in the heap) and bufferByteOffset that the memory location points to. You can also convert a bufferPosition/bufferByteOffset pair to an int pointer with `createPointer(bufferPosition, bufferByteOffset)`. The pointer format is uses 12 bits for the buffer index and the remaining 20 bits for the byte offset in that buffer for a total of 1MB per buffer and 4GB total of memory. Each allocated memory object can return either a pointer via `allocatedMemory.pointer` or the raw position/byte offset via `allocatedMemory.getSharedMemory()`.
|
|
8
|
+
|
|
9
|
+
When passing memory to another thread you can either pass a pointer or a serialized version of the buffer position/byte offset in order to re-create the object in the other thread.
|
|
10
|
+
|
|
11
|
+
## Data Structures
|
|
12
|
+
- SharedList
|
|
13
|
+
- SharedVector
|
|
14
|
+
- SharedMap
|
|
15
|
+
- SharedString
|
|
16
|
+
|
|
17
|
+
## Thread Safety
|
|
18
|
+
- Memory allocations is thread safe as long as it does not need to create a new buffer. Right now that can only be done from the main thread.
|
|
19
|
+
- SharedList, SharedVector, and SharedMap are all not thread safe.
|
|
20
|
+
- SharedString is thread safe with a lock on read/write with a cached version of the string so it doesn't need to lock after the first read unless the string has changed.
|
|
21
|
+
|
|
22
|
+
## TODO
|
|
23
|
+
- Make creating new buffers from allocations possible from multiple threads
|
|
24
|
+
- Make data structures thread safe
|
|
25
|
+
- Add basic thread safe object example
|
|
26
|
+
|
|
27
|
+
## Credit
|
|
28
|
+
The entire core of this library is based on a fork of @thi.ng/malloc found at https://github.com/thi-ng/umbrella/blob/develop/packages/malloc. The only big difference between our MemoryBuffer and their MemPool is making allocations/freeing memory thread safe.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daneren2005/shared-memory-objects",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"author": "daneren2005@gmail.com",
|
|
5
5
|
"description": "Creating objects with a SharedArrayBuffer",
|
|
6
6
|
"homepage": "https://github.com/daneren2005/shared-memory-objects#readme",
|
|
@@ -17,9 +17,13 @@
|
|
|
17
17
|
},
|
|
18
18
|
"type": "module",
|
|
19
19
|
"files": [
|
|
20
|
-
"src/"
|
|
20
|
+
"src/",
|
|
21
|
+
"!__tests__"
|
|
21
22
|
],
|
|
22
23
|
"main": "./src/main.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./src/main.ts"
|
|
26
|
+
},
|
|
23
27
|
"scripts": {
|
|
24
28
|
"dev": "vite",
|
|
25
29
|
"lint": "eslint src/ --ext .js,.cjs,.mjs,.ts,.cts,.mts --ignore-path .gitignore",
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import AllocatedMemory from '../allocated-memory';
|
|
2
|
-
import MemoryHeap from '../memory-heap';
|
|
3
|
-
|
|
4
|
-
describe('MemoryHeap', () => {
|
|
5
|
-
it('auto grows memory as needed', () => {
|
|
6
|
-
let memory = new MemoryHeap({ bufferSize: 200 });
|
|
7
|
-
const startedUsed = memory.currentUsed;
|
|
8
|
-
|
|
9
|
-
let allocated = memory.allocUI32(10);
|
|
10
|
-
expect(allocated.data.length).toEqual(10);
|
|
11
|
-
memory.allocUI32(10);
|
|
12
|
-
expect(memory.buffers.length).toEqual(1);
|
|
13
|
-
// Don't try to get exact size since actual used memory depends on how much memory malloc is using for internal representation
|
|
14
|
-
expect(memory.currentUsed).toBeGreaterThan(startedUsed + 20 * 4);
|
|
15
|
-
expect(memory.totalAllocated).toEqual(200);
|
|
16
|
-
const midUsed = memory.currentUsed;
|
|
17
|
-
|
|
18
|
-
memory.allocUI32(20);
|
|
19
|
-
expect(memory.buffers.length).toEqual(2);
|
|
20
|
-
expect(memory.currentUsed).toBeGreaterThan(midUsed + 20 * 4);
|
|
21
|
-
expect(memory.totalAllocated).toEqual(400);
|
|
22
|
-
});
|
|
23
|
-
it('can re-create from raw memory and continue working', () => {
|
|
24
|
-
let mainMemory = new MemoryHeap({ bufferSize: 200 });
|
|
25
|
-
let copyMemory = new MemoryHeap({
|
|
26
|
-
buffers: mainMemory.buffers.map(buffer => buffer.buf as SharedArrayBuffer)
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
let mainBlock = mainMemory.allocUI32(10);
|
|
30
|
-
let copyBlock = new AllocatedMemory(copyMemory, mainBlock.getSharedMemory());
|
|
31
|
-
expect(copyBlock.data.length).toEqual(12);
|
|
32
|
-
|
|
33
|
-
mainBlock.data[1] = 10;
|
|
34
|
-
expect(copyBlock.data[1]).toEqual(10);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('grabs free memory from any used buffer', () => {
|
|
38
|
-
let memory = new MemoryHeap({ bufferSize: 200 });
|
|
39
|
-
|
|
40
|
-
let block1 = memory.allocUI32(20);
|
|
41
|
-
let block2 = memory.allocUI32(20);
|
|
42
|
-
let block3 = memory.allocUI32(20);
|
|
43
|
-
expect(memory.buffers.length).toEqual(3);
|
|
44
|
-
let maxMemory = memory.currentUsed;
|
|
45
|
-
|
|
46
|
-
block1.free();
|
|
47
|
-
expect(memory.currentUsed).toBeLessThan(maxMemory);
|
|
48
|
-
memory.allocUI32(20);
|
|
49
|
-
expect(memory.buffers.length).toEqual(3);
|
|
50
|
-
expect(memory.currentUsed).toEqual(maxMemory);
|
|
51
|
-
|
|
52
|
-
block2.free();
|
|
53
|
-
expect(memory.currentUsed).toBeLessThan(maxMemory);
|
|
54
|
-
memory.allocUI32(20);
|
|
55
|
-
expect(memory.buffers.length).toEqual(3);
|
|
56
|
-
expect(memory.currentUsed).toEqual(maxMemory);
|
|
57
|
-
|
|
58
|
-
block3.free();
|
|
59
|
-
expect(memory.currentUsed).toBeLessThan(maxMemory);
|
|
60
|
-
memory.allocUI32(20);
|
|
61
|
-
expect(memory.buffers.length).toEqual(3);
|
|
62
|
-
expect(memory.currentUsed).toEqual(maxMemory);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('growing memory by doubles while freeing previous', () => {
|
|
66
|
-
let memory = new MemoryHeap({
|
|
67
|
-
bufferSize: 1_024 * 16
|
|
68
|
-
});
|
|
69
|
-
let allocSize = 40;
|
|
70
|
-
|
|
71
|
-
let oldMemory = memory.allocUI32(allocSize);
|
|
72
|
-
for(let i = 0; i < 5; i++) {
|
|
73
|
-
allocSize *= 2;
|
|
74
|
-
let newMemory = memory.allocUI32(allocSize);
|
|
75
|
-
expect(newMemory.bufferByteOffset).toBeGreaterThan(oldMemory.bufferByteOffset);
|
|
76
|
-
|
|
77
|
-
oldMemory.free();
|
|
78
|
-
oldMemory = newMemory;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('Block creating with bufferSize greater than 1MB', () => {
|
|
83
|
-
let error: Error | null = null;
|
|
84
|
-
try {
|
|
85
|
-
new MemoryHeap({ bufferSize: Math.pow(2, 30) });
|
|
86
|
-
} catch(e) {
|
|
87
|
-
error = e as Error;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
expect(error).not.toBeNull();
|
|
91
|
-
});
|
|
92
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import MemoryHeap from '../memory-heap';
|
|
2
|
-
import { serializeObjectToMemory, createObjectFromMemory } from '../serialize-object';
|
|
3
|
-
|
|
4
|
-
describe('SerializeObject', () => {
|
|
5
|
-
let heap: MemoryHeap;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
heap = new MemoryHeap();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('simple', () => {
|
|
11
|
-
const object = {
|
|
12
|
-
test: 12.5,
|
|
13
|
-
test2: 'string',
|
|
14
|
-
fa: 'blue'
|
|
15
|
-
};
|
|
16
|
-
let memory = serializeObjectToMemory(heap, object);
|
|
17
|
-
|
|
18
|
-
let clone = createObjectFromMemory<typeof object>(memory);
|
|
19
|
-
expect(clone.test).toEqual(12.5);
|
|
20
|
-
expect(clone.test2).toEqual('string');
|
|
21
|
-
expect(clone.fa).toEqual('blue');
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { bench } from 'vitest';
|
|
2
|
-
import SharedList from '../shared-list';
|
|
3
|
-
import MemoryHeap from '../memory-heap';
|
|
4
|
-
import SharedMap from '../shared-map';
|
|
5
|
-
import SharedVector from '../shared-vector';
|
|
6
|
-
|
|
7
|
-
const INSERT_COUNT = 1_000;
|
|
8
|
-
describe(`Shared Data Structures: ${INSERT_COUNT} inserts`, () => {
|
|
9
|
-
bench('shared list', () => {
|
|
10
|
-
let memory = new MemoryHeap();
|
|
11
|
-
let list = new SharedList(memory);
|
|
12
|
-
|
|
13
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
14
|
-
list.insert(Math.random() * 1_000_000);
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
bench('shared map', () => {
|
|
18
|
-
let memory = new MemoryHeap();
|
|
19
|
-
let list = new SharedMap<number>(memory);
|
|
20
|
-
|
|
21
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
22
|
-
list.set(Math.random() * 1_000_000, Math.random() * 1_000_000);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
bench('shared vector', () => {
|
|
26
|
-
let memory = new MemoryHeap();
|
|
27
|
-
let list = new SharedVector(memory);
|
|
28
|
-
|
|
29
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
30
|
-
list.push(Math.random() * 1_000_000);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
bench('shared vector with correct amount initialized', () => {
|
|
34
|
-
let memory = new MemoryHeap();
|
|
35
|
-
let list = new SharedVector(memory, {
|
|
36
|
-
bufferLength: INSERT_COUNT + 2
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
40
|
-
list.push(Math.random() * 1_000_000);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
bench('native array', () => {
|
|
44
|
-
let list: Array<number> = [];
|
|
45
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
46
|
-
list.push(Math.random() * 1_000_000);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const DELETE_COUNT = 1_000;
|
|
52
|
-
describe(`Shared Data Structures: ${DELETE_COUNT} deletes end element`, () => {
|
|
53
|
-
const INSERT_COUNT = 2_000;
|
|
54
|
-
|
|
55
|
-
let sharedList: SharedList;
|
|
56
|
-
bench('shared list', () => {
|
|
57
|
-
for(let i = 0; i < DELETE_COUNT; i++) {
|
|
58
|
-
sharedList.deleteIndex(0);
|
|
59
|
-
}
|
|
60
|
-
}, {
|
|
61
|
-
setup: (task) => {
|
|
62
|
-
task.opts.beforeEach = () => {
|
|
63
|
-
let memory = new MemoryHeap();
|
|
64
|
-
sharedList = new SharedList(memory);
|
|
65
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
66
|
-
sharedList.insert(Math.random() * 1_000_000);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
let sharedVector: SharedVector;
|
|
73
|
-
bench('shared vector', () => {
|
|
74
|
-
for(let i = 0; i < DELETE_COUNT; i++) {
|
|
75
|
-
sharedVector.pop();
|
|
76
|
-
}
|
|
77
|
-
}, {
|
|
78
|
-
setup: (task) => {
|
|
79
|
-
task.opts.beforeEach = () => {
|
|
80
|
-
let memory = new MemoryHeap({
|
|
81
|
-
bufferSize: 1024 * 16
|
|
82
|
-
});
|
|
83
|
-
sharedVector = new SharedVector(memory);
|
|
84
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
85
|
-
sharedVector.push(Math.random() * 1_000_000);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
let nativeList: Array<number> = [];
|
|
92
|
-
bench('native array', () => {
|
|
93
|
-
for(let i = 0; i < DELETE_COUNT; i++) {
|
|
94
|
-
nativeList.pop();
|
|
95
|
-
}
|
|
96
|
-
}, {
|
|
97
|
-
setup: (task) => {
|
|
98
|
-
task.opts.beforeEach = () => {
|
|
99
|
-
nativeList = [];
|
|
100
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
101
|
-
nativeList.push(Math.random() * 1_000_000);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe(`Shared Data Structures: ${DELETE_COUNT} deletes random element`, () => {
|
|
109
|
-
const INSERT_COUNT = 2_000;
|
|
110
|
-
|
|
111
|
-
let sharedList: SharedList;
|
|
112
|
-
bench('shared list', () => {
|
|
113
|
-
for(let i = 0; i < DELETE_COUNT; i++) {
|
|
114
|
-
sharedList.deleteIndex(randomIndex(sharedList));
|
|
115
|
-
}
|
|
116
|
-
}, {
|
|
117
|
-
setup: (task) => {
|
|
118
|
-
task.opts.beforeEach = () => {
|
|
119
|
-
let memory = new MemoryHeap();
|
|
120
|
-
sharedList = new SharedList(memory);
|
|
121
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
122
|
-
sharedList.insert(Math.random() * 1_000_000);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
let sharedVector: SharedVector;
|
|
129
|
-
bench('shared vector', () => {
|
|
130
|
-
for(let i = 0; i < DELETE_COUNT; i++) {
|
|
131
|
-
sharedVector.deleteIndex(randomIndex(sharedList));
|
|
132
|
-
}
|
|
133
|
-
}, {
|
|
134
|
-
setup: (task) => {
|
|
135
|
-
task.opts.beforeEach = () => {
|
|
136
|
-
let memory = new MemoryHeap({
|
|
137
|
-
bufferSize: 1024 * 16
|
|
138
|
-
});
|
|
139
|
-
sharedVector = new SharedVector(memory);
|
|
140
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
141
|
-
sharedVector.push(Math.random() * 1_000_000);
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
let nativeList: Array<number> = [];
|
|
148
|
-
bench('native array', () => {
|
|
149
|
-
for(let i = 0; i < DELETE_COUNT; i++) {
|
|
150
|
-
nativeList.splice(randomIndex(nativeList), 1);
|
|
151
|
-
}
|
|
152
|
-
}, {
|
|
153
|
-
setup: (task) => {
|
|
154
|
-
task.opts.beforeEach = () => {
|
|
155
|
-
nativeList = [];
|
|
156
|
-
for(let i = 0; i < INSERT_COUNT; i++) {
|
|
157
|
-
nativeList.push(Math.random() * 1_000_000);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
function randomIndex(array: { length: number }) {
|
|
165
|
-
return Math.floor(Math.random() * array.length);
|
|
166
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import SharedList from '../shared-list';
|
|
2
|
-
import MemoryHeap from '../memory-heap';
|
|
3
|
-
|
|
4
|
-
describe('SharedList', () => {
|
|
5
|
-
let memory: MemoryHeap;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
memory = new MemoryHeap();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('can insert items', () => {
|
|
11
|
-
let list = new SharedList(memory);
|
|
12
|
-
|
|
13
|
-
list.insert(5);
|
|
14
|
-
expect(list.length).toEqual(1);
|
|
15
|
-
|
|
16
|
-
list.insert(10);
|
|
17
|
-
list.insert(4);
|
|
18
|
-
expect(list.length).toEqual(3);
|
|
19
|
-
|
|
20
|
-
expect(flat(list)).toEqual([5, 10, 4]);
|
|
21
|
-
});
|
|
22
|
-
it('can delete items by index', () => {
|
|
23
|
-
let list = new SharedList(memory);
|
|
24
|
-
let startMemory = memory.currentUsed;
|
|
25
|
-
list.insert(5);
|
|
26
|
-
list.insert(10);
|
|
27
|
-
list.insert(4);
|
|
28
|
-
list.insert(8);
|
|
29
|
-
list.insert(20);
|
|
30
|
-
let fullMemory = memory.currentUsed;
|
|
31
|
-
|
|
32
|
-
list.deleteIndex(2);
|
|
33
|
-
expect(flat(list)).toEqual([5, 10, 8, 20]);
|
|
34
|
-
expect(memory.currentUsed).toBeLessThan(fullMemory);
|
|
35
|
-
expect(list.length).toEqual(4);
|
|
36
|
-
|
|
37
|
-
list.deleteIndex(0);
|
|
38
|
-
expect(flat(list)).toEqual([10, 8, 20]);
|
|
39
|
-
list.deleteIndex(2);
|
|
40
|
-
expect(flat(list)).toEqual([10, 8]);
|
|
41
|
-
|
|
42
|
-
// Do nothing for bug deletes
|
|
43
|
-
list.deleteIndex(2);
|
|
44
|
-
expect(flat(list)).toEqual([10, 8]);
|
|
45
|
-
|
|
46
|
-
// Delete everything and should still work
|
|
47
|
-
list.deleteIndex(0);
|
|
48
|
-
list.deleteIndex(0);
|
|
49
|
-
expect(flat(list)).toEqual([]);
|
|
50
|
-
expect(list.length).toEqual(0);
|
|
51
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
52
|
-
|
|
53
|
-
list.insert(80);
|
|
54
|
-
list.insert(52);
|
|
55
|
-
expect(flat(list)).toEqual([80, 52]);
|
|
56
|
-
});
|
|
57
|
-
it('can delete items by value', () => {
|
|
58
|
-
let list = new SharedList(memory);
|
|
59
|
-
let startMemory = memory.currentUsed;
|
|
60
|
-
list.insert(5);
|
|
61
|
-
list.insert(10);
|
|
62
|
-
list.insert(4);
|
|
63
|
-
list.insert(8);
|
|
64
|
-
list.insert(20);
|
|
65
|
-
let fullMemory = memory.currentUsed;
|
|
66
|
-
|
|
67
|
-
list.deleteValue(4);
|
|
68
|
-
expect(flat(list)).toEqual([5, 10, 8, 20]);
|
|
69
|
-
expect(memory.currentUsed).toBeLessThan(fullMemory);
|
|
70
|
-
expect(list.length).toEqual(4);
|
|
71
|
-
|
|
72
|
-
list.deleteValue(5);
|
|
73
|
-
expect(flat(list)).toEqual([10, 8, 20]);
|
|
74
|
-
list.deleteValue(20);
|
|
75
|
-
expect(flat(list)).toEqual([10, 8]);
|
|
76
|
-
|
|
77
|
-
// Do nothing for bug deletes
|
|
78
|
-
list.deleteValue(15);
|
|
79
|
-
expect(flat(list)).toEqual([10, 8]);
|
|
80
|
-
|
|
81
|
-
// Delete everything and should still work
|
|
82
|
-
list.deleteValue(10);
|
|
83
|
-
list.deleteValue(8);
|
|
84
|
-
expect(flat(list)).toEqual([]);
|
|
85
|
-
expect(list.length).toEqual(0);
|
|
86
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
87
|
-
|
|
88
|
-
list.insert(80);
|
|
89
|
-
list.insert(52);
|
|
90
|
-
expect(flat(list)).toEqual([80, 52]);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('can delete during iteration', () => {
|
|
94
|
-
let list = new SharedList(memory);
|
|
95
|
-
list.insert(5);
|
|
96
|
-
list.insert(10);
|
|
97
|
-
list.insert(4);
|
|
98
|
-
list.insert(8);
|
|
99
|
-
list.insert(20);
|
|
100
|
-
let fullMemory = memory.currentUsed;
|
|
101
|
-
|
|
102
|
-
for(let { data, deleteCurrent } of list) {
|
|
103
|
-
if(data[0] === 10 || data[0] === 20) {
|
|
104
|
-
deleteCurrent();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
expect(flat(list)).toEqual([5, 4, 8]);
|
|
109
|
-
expect(list.length).toEqual(3);
|
|
110
|
-
expect(memory.currentUsed).toBeLessThan(fullMemory);
|
|
111
|
-
|
|
112
|
-
// Delete concurrent indexes
|
|
113
|
-
for(let { data, deleteCurrent } of list) {
|
|
114
|
-
if(data[0] === 5 || data[0] === 4) {
|
|
115
|
-
deleteCurrent();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
expect(flat(list)).toEqual([8]);
|
|
119
|
-
expect(list.length).toEqual(1);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('can insert and delete over and over again without leaking memory', () => {
|
|
123
|
-
let list = new SharedList(memory);
|
|
124
|
-
list.insert(5);
|
|
125
|
-
list.insert(10);
|
|
126
|
-
let startMemory = memory.currentUsed;
|
|
127
|
-
|
|
128
|
-
for(let i = 0; i < 10; i++) {
|
|
129
|
-
list.insert(70);
|
|
130
|
-
list.deleteIndex(2);
|
|
131
|
-
}
|
|
132
|
-
for(let i = 0; i < 10; i++) {
|
|
133
|
-
list.insert(70);
|
|
134
|
-
list.deleteValue(70);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('can share memory and insert/delete items from either instance', () => {
|
|
141
|
-
let mainList = new SharedList(memory);
|
|
142
|
-
let secondList = new SharedList(memory, mainList.getSharedMemory());
|
|
143
|
-
|
|
144
|
-
mainList.insert(5);
|
|
145
|
-
mainList.insert(60);
|
|
146
|
-
secondList.insert(14);
|
|
147
|
-
mainList.insert(8);
|
|
148
|
-
secondList.deleteIndex(1);
|
|
149
|
-
|
|
150
|
-
expect(flat(mainList)).toEqual([5, 14, 8]);
|
|
151
|
-
expect(flat(secondList)).toEqual([5, 14, 8]);
|
|
152
|
-
});
|
|
153
|
-
it.skip('can delete item mid-iteration');
|
|
154
|
-
|
|
155
|
-
it('free', () => {
|
|
156
|
-
let startMemory = memory.currentUsed;
|
|
157
|
-
let list = new SharedList(memory);
|
|
158
|
-
list.insert(5);
|
|
159
|
-
list.insert(10);
|
|
160
|
-
list.insert(4);
|
|
161
|
-
|
|
162
|
-
list.free();
|
|
163
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('with int32', () => {
|
|
167
|
-
let list = new SharedList(memory, {
|
|
168
|
-
type: Int32Array
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
list.insert(5);
|
|
172
|
-
expect(list.length).toEqual(1);
|
|
173
|
-
|
|
174
|
-
list.insert(-10);
|
|
175
|
-
list.insert(4);
|
|
176
|
-
expect(list.length).toEqual(3);
|
|
177
|
-
|
|
178
|
-
expect(flat(list)).toEqual([5, -10, 4]);
|
|
179
|
-
});
|
|
180
|
-
it('with float32', () => {
|
|
181
|
-
let list = new SharedList(memory, {
|
|
182
|
-
type: Float32Array
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
list.insert(5.5);
|
|
186
|
-
expect(list.length).toEqual(1);
|
|
187
|
-
|
|
188
|
-
list.insert(-10);
|
|
189
|
-
list.insert(4);
|
|
190
|
-
expect(list.length).toEqual(3);
|
|
191
|
-
|
|
192
|
-
expect(flat(list)).toEqual([5.5, -10, 4]);
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('with dataLength = 3', () => {
|
|
196
|
-
let list = new SharedList(memory, {
|
|
197
|
-
type: Int32Array,
|
|
198
|
-
dataLength: 3
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
list.insert(5);
|
|
202
|
-
expect(list.length).toEqual(1);
|
|
203
|
-
|
|
204
|
-
list.insert([-10, 20, 1]);
|
|
205
|
-
list.insert([4, -40]);
|
|
206
|
-
expect(list.length).toEqual(3);
|
|
207
|
-
|
|
208
|
-
expect(flat(list)).toEqual([
|
|
209
|
-
5, 0, 0,
|
|
210
|
-
-10, 20, 1,
|
|
211
|
-
4, -40, 0
|
|
212
|
-
]);
|
|
213
|
-
|
|
214
|
-
// Don't delete middle values
|
|
215
|
-
list.deleteValue(20);
|
|
216
|
-
expect(flat(list)).toEqual([
|
|
217
|
-
5, 0, 0,
|
|
218
|
-
-10, 20, 1,
|
|
219
|
-
4, -40, 0
|
|
220
|
-
]);
|
|
221
|
-
|
|
222
|
-
// Allow deleting first value only
|
|
223
|
-
list.deleteValue(-10);
|
|
224
|
-
expect(flat(list)).toEqual([
|
|
225
|
-
5, 0, 0,
|
|
226
|
-
4, -40, 0
|
|
227
|
-
]);
|
|
228
|
-
expect(list.length).toEqual(2);
|
|
229
|
-
|
|
230
|
-
// Allow deleting entire set of values
|
|
231
|
-
list.deleteValue([4, 10, 0]);
|
|
232
|
-
list.deleteValue([5, 0, 0]);
|
|
233
|
-
expect(flat(list)).toEqual([
|
|
234
|
-
4, -40, 0
|
|
235
|
-
]);
|
|
236
|
-
expect(list.length).toEqual(1);
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
function flat(list: SharedList<any>) {
|
|
241
|
-
return [...list].reduce((array, value) => {
|
|
242
|
-
// @ts-expect-error
|
|
243
|
-
array.push(...value.data);
|
|
244
|
-
|
|
245
|
-
return array;
|
|
246
|
-
}, []);
|
|
247
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import MemoryHeap from '../memory-heap';
|
|
2
|
-
import SharedMap from '../shared-map';
|
|
3
|
-
|
|
4
|
-
describe('SharedMap', () => {
|
|
5
|
-
let memory: MemoryHeap;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
memory = new MemoryHeap();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
describe('SharedMap<string>', () => {
|
|
11
|
-
it('insert and remove items', () => {
|
|
12
|
-
let map = new SharedMap<string>(memory);
|
|
13
|
-
|
|
14
|
-
// NOTE: If values are changed make sure we have at least one hash collision
|
|
15
|
-
map.set('ds', 3);
|
|
16
|
-
map.set('asd', 72);
|
|
17
|
-
map.set('gfredf', 8);
|
|
18
|
-
map.set('z', 65);
|
|
19
|
-
// Map should only have one instance of each key - replace
|
|
20
|
-
map.set('ds', 1);
|
|
21
|
-
map.set('red', 10);
|
|
22
|
-
expect(map.length).toEqual(5);
|
|
23
|
-
|
|
24
|
-
expect(map.get('gfredf')).toEqual(8);
|
|
25
|
-
expect(map.get('ds')).toEqual(1);
|
|
26
|
-
expect(map.get('z')).toEqual(65);
|
|
27
|
-
expect(map.get('blue')).toBeUndefined();
|
|
28
|
-
expect(map.get('red')).toEqual(10);
|
|
29
|
-
|
|
30
|
-
map.delete('ds');
|
|
31
|
-
expect(map.length).toEqual(4);
|
|
32
|
-
expect(map.get('ds')).toEqual(undefined);
|
|
33
|
-
map.delete('ds');
|
|
34
|
-
expect(map.length).toEqual(4);
|
|
35
|
-
|
|
36
|
-
map.delete('dfsdfsd');
|
|
37
|
-
expect(map.length).toEqual(4);
|
|
38
|
-
map.delete('gfredf');
|
|
39
|
-
expect(map.length).toEqual(3);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('free', () => {
|
|
43
|
-
let startMemory = memory.currentUsed;
|
|
44
|
-
let map = new SharedMap<string>(memory);
|
|
45
|
-
map.set('ds', 3);
|
|
46
|
-
map.set('asd', 72);
|
|
47
|
-
map.set('gfredf', 8);
|
|
48
|
-
map.set('z', 65);
|
|
49
|
-
|
|
50
|
-
map.free();
|
|
51
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('can be created from shared memory', () => {
|
|
55
|
-
let startMemory = memory.currentUsed;
|
|
56
|
-
let mainMap = new SharedMap<string>(memory);
|
|
57
|
-
let cloneMap = new SharedMap<string>(memory, mainMap.getSharedMemory());
|
|
58
|
-
|
|
59
|
-
mainMap.set('ds', 3);
|
|
60
|
-
mainMap.set('asd', 72);
|
|
61
|
-
cloneMap.set('ds', 1);
|
|
62
|
-
cloneMap.set('red', 10);
|
|
63
|
-
|
|
64
|
-
expect(mainMap.length).toEqual(3);
|
|
65
|
-
expect(cloneMap.length).toEqual(3);
|
|
66
|
-
|
|
67
|
-
expect(mainMap.get('ds')).toEqual(1);
|
|
68
|
-
expect(cloneMap.get('ds')).toEqual(1);
|
|
69
|
-
|
|
70
|
-
cloneMap.free();
|
|
71
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('inserting many items will grow hash table', () => {
|
|
75
|
-
let map = new SharedMap<string>(memory);
|
|
76
|
-
const previousMaxHash = map.maxHash;
|
|
77
|
-
for(let i = 0; i < 5; i++) {
|
|
78
|
-
insertRandom(map);
|
|
79
|
-
}
|
|
80
|
-
expect(map.length).toEqual(5);
|
|
81
|
-
|
|
82
|
-
expect(map.maxHash).toEqual(previousMaxHash);
|
|
83
|
-
for(let i = 0; i < 20; i++) {
|
|
84
|
-
insertRandom(map);
|
|
85
|
-
}
|
|
86
|
-
expect(map.length).toEqual(25);
|
|
87
|
-
expect(map.maxHash).toBeGreaterThan(previousMaxHash);
|
|
88
|
-
|
|
89
|
-
for(let i = 0; i < map.length; i++) {
|
|
90
|
-
expect(map.get(`${i + 1}`)).not.toBeUndefined();
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
function insertRandom(map: SharedMap<string>) {
|
|
95
|
-
map.set(`${map.length + 1}`, Math.random() * 1_000_000);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import MemoryHeap from '../memory-heap';
|
|
2
|
-
import SharedString from '../shared-string';
|
|
3
|
-
|
|
4
|
-
describe('SharedString', () => {
|
|
5
|
-
it('can create', () => {
|
|
6
|
-
let memory = new MemoryHeap();
|
|
7
|
-
let string = new SharedString(memory, 'Test');
|
|
8
|
-
|
|
9
|
-
expect(string.value).toEqual('Test');
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('utf16 characters work', () => {
|
|
13
|
-
let memory = new MemoryHeap();
|
|
14
|
-
let string = new SharedString(memory, 'Teǭst');
|
|
15
|
-
|
|
16
|
-
expect(string.value).toEqual('Teǭst');
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('can initialize from memory without the string allocated yet', () => {
|
|
20
|
-
let memory = new MemoryHeap();
|
|
21
|
-
let allocatedMemory = memory.allocUI32(SharedString.ALLOCATE_COUNT);
|
|
22
|
-
let string = new SharedString(memory, {
|
|
23
|
-
...allocatedMemory.getSharedMemory(),
|
|
24
|
-
value: 'Test'
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
expect(string.value).toEqual('Test');
|
|
28
|
-
});
|
|
29
|
-
it('can work from uninitialized memory', () => {
|
|
30
|
-
let memory = new MemoryHeap();
|
|
31
|
-
let allocatedMemory = memory.allocUI32(SharedString.ALLOCATE_COUNT);
|
|
32
|
-
let string = new SharedString(memory, allocatedMemory.getSharedMemory());
|
|
33
|
-
|
|
34
|
-
expect(string.value).toEqual('');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('can be set to new memory strings', () => {
|
|
38
|
-
let memory = new MemoryHeap();
|
|
39
|
-
let string = new SharedString(memory, 'Tests again22222222222222222222');
|
|
40
|
-
let startMemory = memory.currentUsed;
|
|
41
|
-
let copy = new SharedString(memory, string.getSharedMemory());
|
|
42
|
-
|
|
43
|
-
expect(copy.value).toEqual('Tests again22222222222222222222');
|
|
44
|
-
|
|
45
|
-
copy.value = 'Blows again22222222222222222222';
|
|
46
|
-
expect(string.value).toEqual('Blows again22222222222222222222');
|
|
47
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
48
|
-
|
|
49
|
-
string.value = 'Yo';
|
|
50
|
-
expect(string.value).toEqual('Yo');
|
|
51
|
-
expect(copy.value).toEqual('Yo');
|
|
52
|
-
expect(memory.currentUsed).toBeLessThan(startMemory);
|
|
53
|
-
|
|
54
|
-
string.value = 'Yo Mama Is So Fat2222222222222222222222222222222222222222';
|
|
55
|
-
expect(memory.currentUsed).toBeGreaterThan(startMemory);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('can set to empty string', () => {
|
|
59
|
-
let memory = new MemoryHeap();
|
|
60
|
-
let string = new SharedString(memory, '');
|
|
61
|
-
|
|
62
|
-
expect(string.value).toEqual('');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('free', () => {
|
|
66
|
-
let memory = new MemoryHeap();
|
|
67
|
-
let startMemory = memory.currentUsed;
|
|
68
|
-
let string = new SharedString(memory, 'Tests');
|
|
69
|
-
// No memory leak from changing values
|
|
70
|
-
string.value = 'Blob';
|
|
71
|
-
string.free();
|
|
72
|
-
|
|
73
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import MemoryHeap from '../memory-heap';
|
|
2
|
-
import SharedVector from '../shared-vector';
|
|
3
|
-
|
|
4
|
-
describe('SharedVector', () => {
|
|
5
|
-
let memory: MemoryHeap;
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
memory = new MemoryHeap({
|
|
8
|
-
bufferSize: 1024 * 16
|
|
9
|
-
});
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('insert into vector', () => {
|
|
13
|
-
let vector = new SharedVector(memory, {
|
|
14
|
-
type: Uint32Array
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
vector.push(10);
|
|
18
|
-
vector.push(52);
|
|
19
|
-
vector.push(4);
|
|
20
|
-
|
|
21
|
-
expect(vector.length).toEqual(3);
|
|
22
|
-
expect(flat(vector)).toEqual([10, 52, 4]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('continually grows memory as needed', () => {
|
|
26
|
-
let vector = new SharedVector(memory, {
|
|
27
|
-
type: Uint32Array
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const expectedValues = [];
|
|
31
|
-
for(let i = 0; i < 1_000; i++) {
|
|
32
|
-
vector.push(i);
|
|
33
|
-
expectedValues.push(i);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
expect(vector.length).toEqual(1_000);
|
|
37
|
-
expect(flat(vector)).toEqual(expectedValues);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('pop', () => {
|
|
41
|
-
let vector = new SharedVector(memory);
|
|
42
|
-
|
|
43
|
-
vector.push(10);
|
|
44
|
-
vector.push(52);
|
|
45
|
-
vector.push(4);
|
|
46
|
-
vector.push(8);
|
|
47
|
-
|
|
48
|
-
expect([...vector.pop()]).toEqual([8]);
|
|
49
|
-
expect(vector.length).toEqual(3);
|
|
50
|
-
expect([...vector.pop()]).toEqual([4]);
|
|
51
|
-
expect(vector.length).toEqual(2);
|
|
52
|
-
expect(flat(vector)).toEqual([10, 52]);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('deleteIndex', () => {
|
|
56
|
-
let vector = new SharedVector(memory);
|
|
57
|
-
|
|
58
|
-
vector.push(10);
|
|
59
|
-
vector.push(52);
|
|
60
|
-
vector.push(4);
|
|
61
|
-
vector.push(8);
|
|
62
|
-
|
|
63
|
-
vector.deleteIndex(3);
|
|
64
|
-
expect(vector.length).toEqual(3);
|
|
65
|
-
expect(flat(vector)).toEqual([10, 52, 4]);
|
|
66
|
-
|
|
67
|
-
vector.deleteIndex(1);
|
|
68
|
-
expect(vector.length).toEqual(2);
|
|
69
|
-
expect(flat(vector)).toEqual([10, 4]);
|
|
70
|
-
|
|
71
|
-
vector.deleteIndex(0);
|
|
72
|
-
expect(vector.length).toEqual(1);
|
|
73
|
-
expect(flat(vector)).toEqual([4]);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('with dataLength: 3', () => {
|
|
77
|
-
let vector = new SharedVector(memory, {
|
|
78
|
-
type: Uint32Array,
|
|
79
|
-
dataLength: 3
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
vector.push(10);
|
|
83
|
-
vector.push([52, 32, 6]);
|
|
84
|
-
vector.push([40, 41, 42]);
|
|
85
|
-
|
|
86
|
-
expect(vector.length).toEqual(3);
|
|
87
|
-
expect(flat(vector)).toEqual([
|
|
88
|
-
10, 0, 0,
|
|
89
|
-
52, 32, 6,
|
|
90
|
-
40, 41, 42
|
|
91
|
-
]);
|
|
92
|
-
|
|
93
|
-
expect([...vector.pop()]).toEqual([40, 41, 42]);
|
|
94
|
-
expect(vector.length).toEqual(2);
|
|
95
|
-
expect(flat(vector)).toEqual([
|
|
96
|
-
10, 0, 0,
|
|
97
|
-
52, 32, 6
|
|
98
|
-
]);
|
|
99
|
-
|
|
100
|
-
vector.deleteIndex(0);
|
|
101
|
-
expect(vector.length).toEqual(1);
|
|
102
|
-
expect(flat(vector)).toEqual([
|
|
103
|
-
52, 32, 6
|
|
104
|
-
]);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('can work from memory', () => {
|
|
108
|
-
let mainVector = new SharedVector(memory, {
|
|
109
|
-
type: Uint32Array,
|
|
110
|
-
dataLength: 3
|
|
111
|
-
});
|
|
112
|
-
let cloneVector = new SharedVector(memory, mainVector.getSharedMemory());
|
|
113
|
-
|
|
114
|
-
mainVector.push(10);
|
|
115
|
-
mainVector.push([52, 32, 6]);
|
|
116
|
-
mainVector.push([40, 41, 42]);
|
|
117
|
-
|
|
118
|
-
expect(mainVector.length).toEqual(3);
|
|
119
|
-
expect(flat(mainVector)).toEqual([
|
|
120
|
-
10, 0, 0,
|
|
121
|
-
52, 32, 6,
|
|
122
|
-
40, 41, 42
|
|
123
|
-
]);
|
|
124
|
-
expect(cloneVector.length).toEqual(3);
|
|
125
|
-
expect(flat(cloneVector)).toEqual([
|
|
126
|
-
10, 0, 0,
|
|
127
|
-
52, 32, 6,
|
|
128
|
-
40, 41, 42
|
|
129
|
-
]);
|
|
130
|
-
|
|
131
|
-
// Make sure growing works
|
|
132
|
-
for(let i = 0; i < 10; i++) {
|
|
133
|
-
cloneVector.push(i);
|
|
134
|
-
}
|
|
135
|
-
for(let i = 0; i < 10; i++) {
|
|
136
|
-
mainVector.push(i);
|
|
137
|
-
}
|
|
138
|
-
expect(mainVector.length).toEqual(23);
|
|
139
|
-
expect(cloneVector.length).toEqual(23);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('free', () => {
|
|
143
|
-
let startMemory = memory.currentUsed;
|
|
144
|
-
let vector = new SharedVector(memory, {
|
|
145
|
-
type: Uint32Array
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
for(let i = 0; i < 1_000; i++) {
|
|
149
|
-
vector.push(i);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
vector.free();
|
|
153
|
-
expect(memory.currentUsed).toEqual(startMemory);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
function flat(list: SharedVector<any>) {
|
|
158
|
-
return [...list].reduce((array, value) => {
|
|
159
|
-
array.push(...value);
|
|
160
|
-
|
|
161
|
-
return array;
|
|
162
|
-
}, []);
|
|
163
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { MAX_BYTE_OFFSET_LENGTH, MAX_POSITION_LENGTH, createPointer, getPointer } from '../pointer';
|
|
2
|
-
|
|
3
|
-
describe('pointer', () => {
|
|
4
|
-
it('check all numbers', () => {
|
|
5
|
-
const SKIP_POSITIONS = 10;
|
|
6
|
-
const SKIP_BYTE_OFFSETS = 10;
|
|
7
|
-
|
|
8
|
-
for(let position = 0; position < MAX_POSITION_LENGTH; position += SKIP_POSITIONS) {
|
|
9
|
-
for(let byteOffset = 1; byteOffset < MAX_BYTE_OFFSET_LENGTH; byteOffset *= SKIP_BYTE_OFFSETS) {
|
|
10
|
-
let pointer = createPointer(position, byteOffset);
|
|
11
|
-
|
|
12
|
-
let { bufferPosition, bufferByteOffset } = getPointer(pointer);
|
|
13
|
-
expect(bufferPosition).toEqual(position);
|
|
14
|
-
expect(bufferByteOffset).toEqual(byteOffset);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
});
|