Skip to content
Visit booth 3171 at Google Cloud Next to see how to unlock real-time decisions at scaleMore info

Best practices

Optimizing Performance

The Aerospike Go client library provides tools to optimize performance for different workloads. For the best possible performance, benchmark and profile your application under production workloads.

Client Design Goals

  • Minimal Memory Allocation: Aerospike removes as many allocations as possible by pooling buffers and hash objects whenever possible.

  • Customization Friendly: Use the Aerospike Go client library parameters to customize variables that influence performance under different workloads.

  • Determinism: Aerospike keeps client inner workings deterministic, and avoids data structures and algorithms that are not deterministic. All pool and queue implementations in the client are bound in maximum memory size and perform in a predetermined number of cycles. There are no heuristic algorithms in the client.

Best Practices

  1. Limit server connections. Each server node has a limited number of file descriptors on the operating system for connections. No matter how big, this resource is limited and can be exhausted by too many connections. Clients pool their connections to database nodes for optimal performance. If node connections are exhausted by existing clients, new clients cannot connect to the database, for example, when launching a new application in the cluster. To guard against this, keep the following guidelines in mind when designing your application:

    • Use only one Client object in your application. Client objects pool connections and synchronize their inner functionality. They are goroutine friendly. Use only one Client object in your application and pass it around.

    • Limit the Client connection pool. The default maximum number of connection pools in a Client object is 256. Even under extreme load on fast metal, clients rarely use more than a quarter of these connections. When no connections are available in the pool, the client opens a new connection to server. If all connections in the pool are open, connections are closed when operations complete to prevent too many connections.

      If the pool is too small, the client connects to the server for each new request, wasting time. If the pool is too large, it wastes server connections.

      At its maximum number of 256 for each client and with proto-fd-max set to 10000 in your server node configuration, 50 clients per server node is a safe practice. This provides 150 high-performing clients, assuming a 3-node cluster. Change the pool size in ClientPolicy, then initialize your Client object using the NewClientWithPolicy(policy *ClientPolicy, hostname string, port int) initializer.

  2. Pool client buffers. The Aerospike Go client library pools buffers to reduce memory allocation, but unbounded memory pools are wasteful and unnecessary. The following guidelines help enforce bounds on buffer pools:

    • Don’t increase buffer sizes. Initial buffer sizes are large enough for most operations (default is 16KiBs).

    • Limit the buffer pool size to the default 512 buffers.

    • Enforce a limit on buffer size. If a buffer is larger than the limit, it is not returned to the pool. The default buffer size limit is 128 KiBs.

    These limits ensure that the pool is deterministic in performance and memory size. The default maximum memory size for a buffer pool is 64MiB. The default values perform well under most circumstances, but the following conditions can impact performance:

    • Initial buffer size too small and final size too large. Each allocation is too small for the operation. For example, with records larger than 128KiB.

    • Pool size too small and initial buffer size too small or final buffer size too large. Buffers are allocated and then dismissed because of average pool size.

    If buffer pool size is a bottleneck in your application, you can change it using SetCommandBufferPool(poolSize, initBufSize, maxBufferSize int). Note that the pool is a package object shared between all clients.

  3. Use Bin objects instead of BinMap in Put operations. Put methods require passing a map for bin values. This allocates an array of bins on each call, iterates on the map, and creates Bin objects. Avoid BinMap allocation by using PutBins to manually pass the bins, allocate []Bin, and iterate over the BinMap. This creates two allocations and an O(n) algorithm.

Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?