You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高效保存最近X个整数:每秒96k次操作下留存30秒数据的最优方案

Memory-Optimal Way to Store the Last 30 Seconds of Data (96k Operations/sec)

Great question—with such a high throughput requirement, memory efficiency and raw speed are non-negotiable here. Let’s break down the best approach:

The Top Choice: Fixed-Size Circular Buffer (Ring Queue)

This is hands down the most memory-efficient and performant solution for your use case. Here’s why:

  • Fixed, minimal memory footprint: You only allocate space for exactly 30 values (no extra overhead from dynamic containers, linked list nodes, or resizing). For example, if you’re storing 4-byte floats, that’s just 120 total bytes—nothing for modern systems.
  • O(1) operations: Inserting new values and retrieving the latest 30 both happen in constant time, which is critical for handling 96k writes per second without bottlenecks.
  • No garbage collection or allocation overhead: Since the buffer is pre-allocated, you avoid the performance spikes and memory fragmentation that come with dynamic memory management.

How It Works

Use a static array to hold your values, plus a single integer pointer to track where the next value should be written:

  1. When a new value arrives, write it to the index pointed to by your pointer.
  2. Increment the pointer, wrapping it back to 0 when it hits 30 (using modulo arithmetic).
  3. To retrieve the last 30 values, start from the current pointer and loop through the array (again using modulo to wrap around).

Example Pseudocode

// Adjust the type (e.g., int, double) to match your data
#define BUFFER_SIZE 30
float value_buffer[BUFFER_SIZE];
unsigned int write_index = 0;

// Optional: Add timestamps if you need to strictly validate 30-second expiration
uint64_t timestamps[BUFFER_SIZE];

void add_new_value(float new_val, uint64_t current_timestamp) {
    value_buffer[write_index] = new_val;
    timestamps[write_index] = current_timestamp;
    // Wrap around to the start when we reach the end of the buffer
    write_index = (write_index + 1) % BUFFER_SIZE;
}

// Retrieve the last 30 values (ordered from oldest to newest)
void get_recent_values(float *output) {
    for (int i = 0; i < BUFFER_SIZE; i++) {
        int read_index = (write_index + i) % BUFFER_SIZE;
        output[i] = value_buffer[read_index];
    }
}

Key Optimizations for Your Throughput

  • Skip timestamp checks if possible: If your data is guaranteed to arrive exactly once per second, the 30th element will always be just over 30 seconds old when replaced. No need to validate timestamps—just overwrite the oldest value directly.
  • Avoid locks in single-threaded scenarios: If writes and reads happen on the same thread, you don’t need any synchronization primitives. For multi-threaded setups, use atomic operations for the write_index instead of heavy mutexes to keep latency low.

Why Other Containers Fall Short

  • Dynamic arrays (e.g., Python lists, Java ArrayLists): Risk of resizing overhead and memory fragmentation, which can cause unpredictable performance at 96k ops/sec.
  • Linked lists: Each node adds pointer overhead (wasting memory) and traversal is slower than a contiguous array.
  • Generic queues (e.g., std::queue): Most use deque under the hood, which has extra container overhead compared to a static array.

内容的提问来源于stack exchange,提问作者Sebaku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 13:18:12