<commit_before>Neks
=======

##### A dead simple key/value server

Neks is an in-memory networked key/value server written in ~200 lines of Haskell.

It is intended to be very easy to modify.

##### Features

- Very simple
- Pretty fast (>1M transactions per second is easy, see [Benchmark](#benchmark))
- Highly concurrent 
- Atomic transactions (e.g. atomic read-and-swap)
- Optional disk persistence (with atomic snapshotting)

##### To build and run:

    cabal sandbox init
    cabal install --only-dependencies
    cabal run Server
    cabal run Client -- <args>

or, with dependencies installed:

    ghc -O2 -threaded Server.hs
    ghc -O2 -threaded Client.hs
    ./Server +RTS -N<number of cores>
    ./Client <args>

To run the Python client:

    python3 Client.py

##### Benchmark:

The server runs on two cores. The client runs

- 50 threads
- 200 requests per thread
- 50 reads and 50 writes per request

Speed depends on latency and bandwidth. Here's what I get on my home machines:

| Avg. Latency | Transactions / Second |
---------------|------------------------
| .1ms (localhost)  | 1,150,000 |
| 3.5ms | 750,000 |
| 40ms  | 110,000 |

##### Protocol:

All network encoding is done using [msgpack](http://msgpack.org).

Messages are preceded by the length of the message, transmitted as a 
64-bit big-endian unsigned integer.

The client sends requests to the server, and the server responds with the results of the requests.

There are 4 kinds of requests:

- Requests to Get key `K`. These are formatted as `[0, K]`. The server sends a response.
- Requests to Set key `K` to value `V`. These are formatted as `[1, K, V]`. The server does not send a response.
- Requests to Delete key `K`. These are formatted as `[2, K]`. The server does not send a response.
- Requests to Atomically evaluate a list of requests `R`. This is formatted as `[3, R]`. The server sends the response as if all requests in `R` had been evaluated normally.

There are 2 kinds of responses:

- Response that the value `V` for requested key `K` was found. This is formatted as `[-1, V]`.
- Response that the value for requested key `K` was not found. This is formatted as `[-2]`.

Example conversation:<commit_msg>New tests<commit_after>Neks
=======

##### A dead simple key/value server

Neks is an in-memory networked key/value server written in ~200 lines of Haskell.

It is intended to be very easy to modify.

##### Features

- Very simple
- Pretty fast (>1M transactions per second is easy, see [Benchmark](#benchmark))
- Highly concurrent 
- Atomic transactions (e.g. atomic read-and-swap)
- Optional disk persistence (with atomic snapshotting)

##### To build and run:

    cabal sandbox init
    cabal install --only-dependencies
    cabal run Server
    cabal run Client -- <args>

or, with dependencies installed:

    ghc -O2 -threaded Server.hs
    ghc -O2 -threaded Client.hs
    ./Server +RTS -N<number of cores>
    ./Client <args>

To run the Python client:

    python3 Client.py

##### Benchmark:

The server and client run on two cores. The client runs

- 50 threads
- 200 requests per thread
- 50 reads and 50 writes per request

Speed depends on latency and bandwidth. Here's what I get on my home machines:

| Avg. Latency | Transactions / Second |
---------------|------------------------
| .1ms (localhost)  | 1,150,000 |
| .3ms (ethernet) | 1,100,000 |
| 3.5ms (wireless) | 750,000 |

##### Protocol:

All network encoding is done using [msgpack](http://msgpack.org).

Messages are preceded by the length of the message, transmitted as a 
64-bit big-endian unsigned integer.

The client sends requests to the server, and the server responds with the results of the requests.

There are 4 kinds of requests:

- Requests to Get key `K`. These are formatted as `[0, K]`. The server sends a response.
- Requests to Set key `K` to value `V`. These are formatted as `[1, K, V]`. The server does not send a response.
- Requests to Delete key `K`. These are formatted as `[2, K]`. The server does not send a response.
- Requests to Atomically evaluate a list of requests `R`. This is formatted as `[3, R]`. The server sends the response as if all requests in `R` had been evaluated normally.

There are 2 kinds of responses:

- Response that the value `V` for requested key `K` was found. This is formatted as `[-1, V]`.
- Response that the value for requested key `K` was not found. This is formatted as `[-2]`.

Example conversation:
{'fraction_non_alphanumeric': 0.11463250168577209, 'fraction_numerical': 0.02247696111485727, 'mean_word_length': 3.1823308270676693, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1388233', 'n_tokens_mistral': 1402, 'n_tokens_neox': 1281, 'n_words': 642}