@vizidrix/libringbufferjs
Version:
Vizidrix - LibRingBufferJS provides a small suite of low level wrappers around a pre-allocated 2s compliment sized auto wrapping buffer
255 lines (161 loc) • 7.26 kB
Markdown
and garbage collection overhead.
By enforcing ring counts as 2s compliments the wrapping mechanism is simplified from variable size rings, where head
and tail index must be tracked in order to provide looping characteristics, down to a simple binary AND (&).
The goal of this library is to provide low level features that can be used to build higher order structures such
as Queues and Pub/Sub that can take advantage of it's internal structure.
Inspired by ideas around mechanical sympathy:
- [Mechanical Sympathy](http://mechanical-sympathy.blogspot.com/)
- [LMAX Disruptor](https://github.com/LMAX-Exchange/disruptor)
> Pre-allocated structures, data element which could be size aligned to optimize for cache lines
[Changelog](https://gitlab.com/vizidrix/libringbufferjs/blob/master/CHANGELOG.md)
### ringbuffer.ts
````typescript
/**
* IRingBuffer provides access methods to interact with the ring buffer structure
*/
export interface IRingBuffer<T> {
/** returns a DataView of the current position and moves the position forward */
claim: () => T
/** returns the current bounded position used to index the ring internally */
getIndex: () => number
/** returns the current, perpetually incrementing, cursor position of the ring buffer */
getPosition: () => number
/** returns the ring's initialization data */
getRingSize: () => number
/** returns a slice cursor to the slice at the specified index within the ring */
peek: (index: number) => T
}
````
````typescript
// example using BianryRingBuffer
import { BinaryRingBuffer } from 'libringbufferjs'
// make a binary ring buffer
let rb = BinaryRingBuffer(4, 16)
// claim a slot - gives a reference to the DataView in the current slot and moves the pointer
let writer = rb.claim()
// put binary data into the slice you claimed
writer.setInt8(0, 10)
// grab a slice cursor at a specified position
let reader = rb.peek(0)
// read the data out of the slice you previously wrote to
let value = reader.getInt8(0)
````
````typescript
// example using RingBuffer
import { RingBuffer } from 'libringbufferjs'
// make a basic object ring buffer with a structure defined inline
let rb = RingBuffer(4, () => {return { value: 0 }})
// claim a slot = gives a reference to the object in the current slot and moves the pointer
let writer = rb.claim()
// update properties of your object
writer.value = 20
// grab an object reference at a specified position
let reader = rb.peek(0)
// read the data out of the object property
let value = reader.value
````
> todo: implement non-binary ring buffer that can pre-fill object instances using a factory (optionally a reset function?) and claim returns a reference that can be mutated
### Usefull libraries
[JavaScript typed arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)
[ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
[DataView](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)
[StringView](https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView)
[ArrayBuffer Playground](http://www.javascripture.com/Int8Array)
## Library
This library depends on [TypeScript](http://www.typescriptlang.org/) to compile:
> Tips for setting up repo for NPM: [Authoring NPM Modules with TypeScript](http://blog.johnnyreilly.com/2015/09/authoring-npm-modules-with-typescript.html)
````bash
npm install -g typescript
````
### Useful NPM Commands
Initializes a freshly cloned repo, downloading npm and typescript packages and other prep
> Caution, this will delete files that aren't linked to Git
````bash
npm run setup
````
Builds the typescript command and generates the es5 compatible version
````bash
npm run compile
````
Runs the tslint utility which reports back any non-conforming instances
> Helps to create a uniform code base by enforcing sytle and naming type of guidelines
````bash
npm run lint
````
Executes the 'tape' test suite and emits the results to the console
````bash
npm run test
````
Executes the benchmarkjs suite and emits the results to the console
````bash
npm run bench
````
Executes compile, lint and test functions and sets up a file watcher to trigger them on each file modification
````bash
npm run dev
````
Executes the typedoc utility which generates documentation for the project based upon the provided types, comments and structures
````bash
npm run docs
````
### Hosted on GitLab
[GitLab - Free Private Repos](http://gitlab.com)
### View Project Runners
[GitLab CI - gitlab.com/vizidrix/typescript_lib_boilerplate](https://gitlab.com/vizidrix/typescript_lib_boilerplate/runners)
### Setup Private Runners
[GitLab CI - Register Runner](http://doc.gitlab.com/ce/ci/docker/using_docker_images.html)
## Development Environment
- Typescript
- Add static typing and related utility to JS IDE
- TSLint
- TypeScript linter to enforce syntax and coding standards
- Tape / Blue-Tape
- Async Unit Testing callable from node
- Istanbul
- Test Coverage Report and Enforcement
- BenchmarkJS
- JavaScript benchmarking library
> Support for multiple targets (es5 and es6) is difficult due to es5 required polyfills
## Documentation
[TypeDoc](http://typedoc.io/)
Keeping documentation up to date is hard, wherever possible keep it next to the item being documented so it stays live.
[Documenting Comments](http://typedoc.io/guides/doccomments.html)
> Setup a pre-commit step to trigger docs generation, need to check if it auto updates prior to commit
````bash
// Generate docs manually
npm run docs
````
### Typescript Definitions
#### From DefiantlyTyped
- blue-tape
- es6-promise
- node
- tape
### TSLint
> TODO: Consider switching / implementing [Standard JS](https://github.com/feross/standard)
See [TSLint - Github](https://github.com/palantir/tslint) for more options and documentation
Excluded options:
````json
"no-any": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-constructor-vars": true,
````
### BenchmarkJS
[Bulletproof JavaScript Benchmarks](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/)
[How it works](http://monsur.hossa.in/2012/12/11/benchmarkjs.html)
## Publishing to NPM
[Publishing TypeScript on NPM](http://blog.charto.net/node-js/Publishing-TypeScript-based-modules-on-npm/)
[Automating Publish with NPM](http://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm)
````bash
npm publish --access=public
````
[ ](https://volkan.io/)
[ ](https://books.google.com/books/about/High_Performance_JavaScript.html?id=ED6ph4WEIoQC&printsec=frontcover&source=kp_read_button#v=onepage&q&f=false)
[ ](https://strongloop.com/strongblog/roll-your-own-node-js-ci-server-with-jenkins-part-2/)
[ ](https://github.com/npm/npm/issues/6124)
[ ](https://ind.ie/labs/blog/installing-npm-packages-from-gitlab-repositories/)
[ ](http://keepachangelog.com/)
Provide a low level mechanism which avoids allocation