爲什麼 Golang Fasthttp 選擇使用 slice 而非 map 存儲請求數據

Fasthttp 是一個高性能的 Golang HTTP 框架,它在設計上做了許多優化以提高性能。其中一個顯著的設計選擇是使用 slice 而非 map 來存儲數據,尤其是在處理 HTTP headers 時。

爲什麼呢?

本文將從簡單到複雜,逐步剖析爲什麼 Fasthttp 選擇使用 slice 而非 map,並通過代碼示例解釋這一選擇背後高性能的原因

Slice vs Map:基本概念

首先,這個設計選擇背後有着深思熟慮的考量,主要圍繞性能優化展開。在深入探討之前,我們需要理解 slice 和 map 在 Go 語言中的基本概念和性能特點。

內存分配和性能

在高性能的應用場景中,內存分配和回收是性能的關鍵因素之一。Fasthttp 在這方面做了考量。

Slice 的內存效率

由於 slice 的元素在內存中是連續存儲的,它們訪問速度快,且能有效利用 CPU 緩存。此外,slice 可以通過重新切片來複用已有的數組,減少內存分配和垃圾回收的壓力。

Map 的內存開銷

相比之下,map 的內存開銷較大。

在 map 中,鍵和值通常是散佈在內存中的,這導致 CPU 緩存利用率不高。而且,map 的增長通常涉及重新哈希和重新分配內存,這些操作在性能敏感的應用中可能成爲瓶頸。

Fasthttp 中的 SliceMap

Fasthttp 選擇使用自定義的 sliceMap 結構來存儲鍵值對,而非標準的 map。

下面是 sliceMap 的一個簡化實現和它的 Add 方法:

type kv struct {
    key []byte
    value []byte
}

type sliceMap []kv

func (sm *sliceMap) Add(k, v []byte) {
    kvs := *sm
    if cap(kvs) > len(kvs) {
        kvs = kvs[:len(kvs)+1]
    } else {
        kvs = append(kvs, kv{})
    }
    kv := &kvs[len(kvs)-1]
    kv.key = append(kv.key[:0], k...)
    kv.value = append(kv.value[:0], v...)
    *sm = kvs
}

在這個設計中,sliceMap 通過以下方式優化性能:

減少內存分配

通過在現有的 slice 上進行操作,sliceMap 儘可能地複用內存。當容量足夠時,它通過重新切片 kvs = kvs[:len(kvs)+1] 來擴展 slice,避免了額外的內存分配。

減少垃圾回收壓力

由於 slice 的元素是連續存儲的,它可以更有效地被垃圾回收器處理,減少了垃圾回收的開銷。而且,由於內存是複用的,垃圾回收的次數也大大減少。

性能優化的深層原因

Fasthttp 使用 sliceMap 而非 map 的決策不僅僅是基於內存和性能的考量,還有更深層的原因:

存儲數據特性

在處理 HTTP 請求時,通常 headers、query 參數或 cookies 的數量並不多。這意味着即使使用線性搜索,查找效率也不會成爲性能瓶頸。

相比之下,雖然 hash map 提供了理論上接近 O(1) 的查找效率,但實際使用中也有其開銷和複雜性。

這些因素在元素數量較少時可能會抵消 hash map 在查找效率上的理論優勢,而 slice 則纔是更優質的選擇。

CPU 預加載特性

由於 slice 的內存佈局是連續的,它符合 CPU 緩存的工作原理,即一次性加載相鄰數據。這種連續性使得 CPU 在訪問一個 slice 元素後,能預加載相鄰元素到緩存中,提高後續訪問的速度。

因此,順序訪問 slice 時,緩存命中率高,減少了對主內存的訪問次數,從而提高了性能。

結論

Fasthttp 的設計選擇反映了對性能細節的深入理解和精心優化。通過使用 slice 而非 map,Fasthttp 在內存分配、垃圾回收以及 CPU 緩存利用等方面實現了優化,爲高性能的 HTTP 應用提供了堅實的基礎。這種設計不僅僅是技術上的選擇,更是對實際應用場景和性能需求的深入洞察。

博文地址:爲什麼 Golang Fasthttp 選擇使用 slice 而非 map 存儲請求數據 [1]

引用鏈接

[1] 爲什麼 Golang Fasthttp 選擇使用 slice 而非 map 存儲請求數據: https://www.poloxue.com/posts/2024-01-18-why-fasthttp-opts-for-slice-over-map/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/849S4pJ0yhKGPRFERHlk8w