Categorygithub.com/Fusl/go-resp
repositorypackage
0.0.0-20241014024022-0c36f80da8e0
Repository: https://github.com/fusl/go-resp.git
Documentation: pkg.go.dev

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# README

go-resp

go-resp is a fast and simple, barebones RESP (Redis serialization protocol) parser and serializer for Go.

Installing

go get -u github.com/Fusl/go-resp

Usage

resp.NewClientConn() accepts a net.Conn and returns a resp.ClientConn which can be used to read and write RESP messages.

Reading

Every ClientConn instance has a Next() method which reads the next RESP message from the connection. The method returns a [][]byte slice containing the RESP message and an error. Care must be taken when reading the message as the slice and the underlying byte slices are reused for every call to Next(). If in doubt, copy the slice and every byte slice it contains to a newly allocated slice and byte slices.

Writing

Every ClientConn instance has various write methods for writing RESP messages to the connection. The methods are named after the RESP message type they write. By default, messages are written in RESP3 compatible format. Calling SetRESP2Compat(true) on a ClientConn instance will make it write messages in RESP2 compatible format instead, even when calling RESP3 methods such as WriteMapBytes() which are not available in RESP2 and therefore converted to arrays.

See the go-resp package documentation for a list of all available write methods and how to use them.

Depending on the state of the internally allocated read buffer, writing may not immediately flush to the client, such as to improve performance when processing pipelined commands. To immediately flush any pending writes, call Flush() on the ClientConn instance.

To prevent flushing after every write, such as when manually writing an array response with a large number of entries, call the Buffer() method on the ClientConn instance which accepts a function that writes the response:

rconn.WriteBuffered(func() error {
    rconn.WriteArrayHeader(2)
    rconn.WriteStatusString("hello")
    rconn.WriteStatusString("world")
    return nil
})

Concurrency

Reading or writing is not thread-safe and should not be done concurrently. You may read with Next() in one goroutine and write with Write() in another goroutine, but you should not call Next() or Write() concurrently.

Example

See example/example.go for a simple example server.

Benchmarks

Benchmark information

Hardware

  • CPU: Intel Core i9-13900KF @ 5.5GHz
  • RAM: 4x 32GB DDR4 @ 3200MHz

Benchmark command

$ redis-benchmark -p <port> -c <clients> -P <numreq> -n 100000000 ping

Standard Redis Server

$ redis-server --port 6379 --appendonly no --save ''
-c-PThroughputlatencyminp50p95p99max
11161,4210.0040.0000.0070.0070.0070.303
110006,930,4880.1120.1040.1190.1190.1190.279
1010009,683,3550.9350.1120.9351.0071.0151.679

go-resp example server (GOMAXPROCS=8)

$ GOMAXPROCS=8 go run ./example/example.go
-c-PThroughputIncreaselatencyminp50p95p99max
11169,964+5.29%0.0040.0000.0070.0070.0070.311
1100011,774,402+69.89%0.0520.0480.0550.0550.0550.159
10100031,318,508+223.43%0.1880.0480.1830.2710.3190.567

go-resp example server (GOMAXPROCS=1)

$ GOMAXPROCS=1 go run ./example/example.go
-c-PThroughputIncreaselatencyminp50p95p99max
11169,330+4.90%0.0040.0000.0070.0070.0070.271
1100011,970,313+72.72%0.0520.0400.0550.0550.0550.199
10100022,456,770+131.91%0.4120.0400.4150.7750.7910.903