Skip to content

Commit

Permalink
Hack in pool for ArrayBuffers used by StructArray.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisLoer committed Dec 13, 2018
1 parent 22ab43e commit 1cf7e1e
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
18 changes: 18 additions & 0 deletions src/data/bucket/symbol_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ class SymbolBuffers {
this.placedSymbolArray = new PlacedSymbolArray();
}

releaseBuffer() {
const keys = Object.keys(this);
for (const key of keys) {
if (this[key] && this[key].releaseBuffer) {
this[key].releaseBuffer();
}
}
}

upload(context: Context, dynamicIndexBuffer: boolean, upload?: boolean, update?: boolean) {
if (upload) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, symbolLayoutAttributes.members);
Expand Down Expand Up @@ -183,6 +192,15 @@ class CollisionBuffers {
this.collisionVertexArray = new CollisionVertexArray();
}

releaseBuffer() {
const keys = Object.keys(this);
for (const key of keys) {
if (this[key] && this[key].releaseBuffer) {
this[key].releaseBuffer();
}
}
}

upload(context: Context) {
this.layoutVertexBuffer = context.createVertexBuffer(this.layoutVertexArray, this.layoutAttributes);
this.indexBuffer = context.createIndexBuffer(this.indexArray);
Expand Down
8 changes: 8 additions & 0 deletions src/source/worker_tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ class WorkerTile {
iconMap: this.returnDependencies ? iconMap : null,
glyphPositions: this.returnDependencies ? glyphAtlas.positions : null
});
values(buckets).filter(b => b.isEmpty()).forEach(emptyBucket => {
const bucketKeys = Object.keys(emptyBucket);
for (const key of bucketKeys) {
if (emptyBucket[key] && emptyBucket[key].releaseBuffer) {
emptyBucket[key].releaseBuffer();
}
}
});
}
}
}
Expand Down
60 changes: 58 additions & 2 deletions src/util/struct_array.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ class Struct {
const DEFAULT_CAPACITY = 128;
const RESIZE_MULTIPLIER = 5;

let resizeCount = 0;
let reuseCount = 0;
let sliceCount = 0;
let noSliceCount = 0;
let sizeCounts = {};
let bufferPool = {};

let constructedTypes = {};
let transferedTypes = {};

export type StructArrayMember = {
name: string,
type: ViewType,
Expand Down Expand Up @@ -140,10 +150,25 @@ class StructArray {
* Resize the array to discard unused capacity.
*/
_trim() {
transferedTypes[this.constructor.name] = true;
if (this.length !== this.capacity) {
const prevSize = this.capacity * this.bytesPerElement;
if (!bufferPool[prevSize]) {
bufferPool[prevSize] = [];
}
bufferPool[prevSize].push(this.arrayBuffer);
this.capacity = this.length;
this.arrayBuffer = this.arrayBuffer.slice(0, this.length * this.bytesPerElement);
sliceCount++;
if (sliceCount % 1000 === 0) {
console.log(`${sliceCount} slices on ${resizeCount} allocations and ${reuseCount} buffers reused from pool, with ${noSliceCount} not requiring slice.`);
// for (const size in sizeCounts) {
// console.log(`${size} allocated ${sizeCounts[size]} times`);
// }
}
this._refreshViews();
} else {
noSliceCount++;
}
}

Expand Down Expand Up @@ -173,15 +198,46 @@ class StructArray {
*/
reserve(n: number) {
if (n > this.capacity) {
this.capacity = Math.max(n, Math.floor(this.capacity * RESIZE_MULTIPLIER), DEFAULT_CAPACITY);
this.arrayBuffer = new ArrayBuffer(this.capacity * this.bytesPerElement);
constructedTypes[this.constructor.name] = true;
const prevSize = this.capacity * this.bytesPerElement;
const exponent = Math.max(0, Math.ceil(Math.log(n * this.bytesPerElement / DEFAULT_CAPACITY) / Math.log(RESIZE_MULTIPLIER)));
const newSize = DEFAULT_CAPACITY * Math.pow(RESIZE_MULTIPLIER, exponent);//Math.max(n, Math.floor(this.capacity * RESIZE_MULTIPLIER), DEFAULT_CAPACITY);
this.capacity = newSize / this.bytesPerElement;
if (!sizeCounts[newSize]) {
sizeCounts[newSize] = 0;
}
sizeCounts[newSize]++;
if (prevSize > 0) {
if (!bufferPool[prevSize]) {
bufferPool[prevSize] = [];
}
bufferPool[prevSize].push(this.arrayBuffer);
}

if (bufferPool[newSize] && bufferPool[newSize].length > 0) {
reuseCount++;
this.arrayBuffer = bufferPool[newSize].pop();
} else {
resizeCount++;
this.arrayBuffer = new ArrayBuffer(this.capacity * this.bytesPerElement);
}

const oldUint8Array = this.uint8;
this._refreshViews();
if (oldUint8Array) this.uint8.set(oldUint8Array);
}
}

releaseBuffer() {
const prevSize = this.capacity * this.bytesPerElement;
if (prevSize > 0) {
if (!bufferPool[prevSize]) {
bufferPool[prevSize] = [];
}
bufferPool[prevSize].push(this.arrayBuffer);
}
}

/**
* Create TypedArray views for the current ArrayBuffer.
*/
Expand Down

0 comments on commit 1cf7e1e

Please sign in to comment.