Skip to content

Commit 521cb8f

Browse files
authored
update buffers section for spectator-go
1 parent c9ff88e commit 521cb8f

File tree

1 file changed

+85
-10
lines changed

1 file changed

+85
-10
lines changed

docs/spectator/lang/go/usage.md

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,91 @@ the environment variable takes precedence over the passed config.
200200

201201
The environment variable `SPECTATOR_OUTPUT_LOCATION` can be set to `none` to disable metrics collection.
202202

203-
## Line Buffer
204-
205-
The `NewConfigWithBuffer` factory function takes a `bufferSize` parameter that configures an optional
206-
`LineBuffer`, which caches protocol lines locally, before flushing them to `spectatord`. Flushes occur
207-
under two conditions: (1) the buffer size is exceeded, or (2) five seconds has elapsed. The buffer is
208-
available for the `UdpWriter` and the `UnixgramWriter`, where performance matters most. The `LineBuffer`
209-
is disabled by default (with size zero) in the standard `NewConfig` factory function, to ensure that the
210-
default operation of the library works under most circumstances. For high-performance scenarios, a 60KB
211-
buffer size is recommended. The maximum buffer size for udp sockets and unix domain sockets on Linux is
212-
64KB, so stay under this limit.
203+
## Buffers
204+
205+
Three modes of operation are available, for applications that operate at different scales:
206+
207+
* **Small.** No buffer (size 0 bytes). Write immediately to the socket upon every metric update, up to
208+
~150K lines/sec, with delays from 1 to 450 us, depending on thread count. No metrics are dropped, due
209+
to mutex locks.
210+
* **Medium.** LineBuffer (size <= 65536 bytes), which writes to the socket upon overflow, or upon a
211+
flush interval, up to ~1M lines/sec, with delays from 0.1 to 32 us, depending on thread count. No metrics
212+
are dropped. Status metrics are published to monitor usage.
213+
* **Large.** LowLatencyBuffer (size > 65536 bytes), which writes to the socket on a flush interval, up
214+
to ~1M lines/sec, with delays from 0.6 to 7 us, depending on thread count. The true minimum size is 2 *
215+
CPU * 60KB, or 122,880 bytes for 1 CPU. Metrics may be dropped. Status metrics are published to monitor
216+
usage.
217+
218+
The buffers are available for the UdpWriter and the UnixWriter.
219+
220+
### Line Buffer (bufferSize <= 65536)
221+
222+
This is a single string buffer, protected by a mutex, that offers write performance up to ~1M lines/sec
223+
(spectatord maximum), with a latency per write ranging from 0.1 to 32 us, depending upon the number of
224+
threads in use.
225+
226+
Metrics are flushed from the buffer when an overflow occurs, and periodically by a timer, according to
227+
the flush interval. Thus, if there are periods of time when metric publishing is slow, metrics will still
228+
be delivered from the buffer on time. Note that the spectatord publish interval is every 5 seconds, which
229+
is a good starting choice for this configuration. This buffer will block, and it will not drop lines.
230+
231+
The LineBuffer reports two metrics, which can be used to monitor buffer performance:
232+
233+
* `spectator-go.lineBuffer.bytesWritten` - A counter reporting bytes/sec written to spectatord.
234+
* `spectator-go.lineBuffer.overflows` - A counter reporting overflows/sec, which are flushes before the
235+
interval.
236+
237+
Example configuration:
238+
239+
```
240+
config, _ := NewConfigWithBuffer("udp", nil, nil, 61440, 5*time.Second)
241+
```
242+
243+
### Low Latency Buffer (bufferSize > 65536)
244+
245+
LowLatencyBuffer (bufferSize > 65536), which builds arrays of buffers that are optimized for introducing
246+
the least amount of latency in highly multithreaded applications that record many metrics. It offers write
247+
performance up to ~1 M lines/sec (spectatord maximum), with a latency per write ranging from 0.6 to 7 us,
248+
depending upon the number of threads in use.
249+
250+
This is achieved by spreading data access across a number of different mutexes, and only writing buffers
251+
from a goroutine that runs periodically, according to the flushInterval. There is a front buffer and a back
252+
buffer, and these are rotated during the periodic flush. The inactive buffer is flushed, while the active
253+
buffer continues to receive metric writes from the application. Within each buffer, there are numCPU shards,
254+
and each buffer shard has N chunks, where a chunk is set to 60KB, to allow the data to fit within the
255+
spectatord socket buffers with room for one last protocol line. This buffer will not block, and it can drop
256+
lines, if it overflows.
257+
258+
As a sizing example, if you have an 8 CPU system, and you want to allocate 5 MB to each buffer shard, and
259+
there are two buffers (front and back), then you need to configure a buffer size of 83,886,080 bytes. Each
260+
buffer shard will have 85 chunks, each of which is protected by a separate mutex.
261+
262+
```
263+
2 buffers (front/back) * 8 CPU (shard count) * 5,242,880 bytes/shard * = 83,886,080 bytes total
264+
```
265+
266+
Pairing this with a 1-second flush interval will result in a configuration that can handle ~85K lines/sec
267+
writes to spectatord. Note that the spectatord publish interval is every 5 seconds, so you have some room to
268+
experiment with different buffer sizes and publish intervals.
269+
270+
While the bufferSize can be set as low as 65537, it will guarantee a minimum size of 2 * CPU * 60KB, to
271+
ensure that there is always at least 1 chunk per shard. On a system with 1 CPU, this will be 122,880 bytes,
272+
and on a system with 4 CPU, this will be 491,520 bytes.
273+
274+
The LowLatencyBuffer reports metrics, which can be used to monitor buffer performance:
275+
276+
* `spectator-go.lowLatencyBuffer.bytesWritten` - A counter reporting bytes/sec written to spectatord.
277+
* `spectator-go.lowLatencyBuffer.overflows` - A counter reporting overflows/sec, which are drops.
278+
* `spectator-go.lowLatencyBuffer.pctUsage` - A gauge reporting the percent usage of the buffers.
279+
280+
When using the LowLatencyBuffer, it is recommended to watch the `spectatord.parsedCount` metric, to ensure
281+
that you have sufficient headroom against the maximum data ingestion rate of ~1M lines/sec for `spectatord`.
282+
283+
Example configuration:
284+
285+
```
286+
config, _ := NewConfigWithBuffer("udp", nil, nil, 83886080, 1*time.Second)
287+
```
213288

214289
## Batch Usage
215290

0 commit comments

Comments
 (0)