搜尋
首頁資料庫RedisRedis的zmalloc函數實例分析

Redis的zmalloc函數實例分析

May 27, 2023 pm 05:50 PM
redis

我們直接來看 Redis 原始碼(不是最新版本)中自訂的 zmalloc 函數,該函數與 malloc 等常規函數的使用方式完全一致,不同的在於其內部的具體實作細節。

# void *zmalloc(size_t size) {

    // 分配記憶體;

#     void *ptr = malloc(size PREFIX_SIZE);

#     // 分配失敗拋出例外;

    if (!ptr) zmalloc_oom_handler(size);

# // 系統是否可以使用”malloc_size“函數?

#ifdef HAVE_MALLOC_SIZE

    update_zmalloc_stat_alloc(zmalloc_size(ptr));

    return ptr;

# #else

#     // 在資料域中保存分配資料的實際大小;

#     *((size_t*)ptr) = size;

    // 計算對齊後的記憶體使用大小,並更新」used_memory「變數;

    update_zmalloc_stat_alloc(size PREFIX_SIZE);

    // 傳回資料體的初始位置;

    return (char*)ptr PREFIX_SIZE;

#endif

# }

其實,標準函式庫中的 malloc 函數已經能夠自動為分配的記憶體實作對齊,因此 zmalloc 方法在這裡其主要目的是為了能夠精確地計算每一次資料儲存時所分配的記憶體大小。在每一次分配記憶體時,zmalloc 都會在該次分配的資料記憶體大小的基礎上再加上一個PREFIX_SIZE 大小的額外記憶體空間,這個PREFIX_SIZE 巨集代表了目前系統的最大記憶體定址空間大小(size_t),其依賴具體係統的類型不同而不同。這裡我們可以簡稱這個 PREFIX_SIZE 大小的空間為一個儲存單元的「資料頭」部分。

初版 Redis 的儲存單元結構

# 如上圖所示,透過*((size_t*)ptr) = size; 語句,Redis 在目前分配記憶體區塊的前PREFIX_SIZE 個位元組,即資料頭內儲存了本次實際分配的資料區塊大小,而在後面」size「 大小的記憶體空間才真正存放了二進位的資料實體。這裡名為 update_zmalloc_stat_alloc 的函數在其內部會維護一個名為 used_memory 的全域變量,該變數累積了每次新分配的記憶體大小。函數在最後傳回了一個偏移的指針,指向了目前分配記憶體的資料體部分。 update_zmalloc_stat_alloc 函數的具體實作細節如下。

#define update_zmalloc_stat_alloc(__n) do { 

#     size_t _n = (__n); 

    // 手動記憶體補齊;

    if (_n&(sizeof(long)-1)) _n = sizeof(long)-(_n&(sizeof(long)-1)); 

#     atomicIncr(used_memory, __n); 

# } while(0)

這裡要注意的重點是 _n = sizeof(long)-(_n&(sizeof(long)-1)); 這行語句。整個巨集函數首先判斷本次分配的記憶體大小是否為sizeof(long) 大小的整數倍(64位元機對應8位元組的記憶體對齊;32位元機則對應4位元組的記憶體對齊),如果不是則透過我們先前給出的語句在該資料段後面加上對應的佔位空間來補足位數以滿足記憶體對齊(4/8位元組)的要求。最後的 atomicIncr 函數用來在保證線程安全的情況下更新全域的 used_memory 變數值。

而該版本 Redis 中記憶體釋放與其記憶體分配的過程則正好相反。如下所示程式碼為對應 ”zfree“ 函數的實作細節。首先該函數透過(char*)ptr-PREFIX_SIZE 語句(向記憶體低位址移動)指向了包含有該資料塊實際佔用大小的資料域首位址,然後透過*((size_t*)realptr) 語句獲得到了該數據區塊分配的真實記憶體大小(不包含記憶體對齊區域)。最後再透過 update_zmalloc_stat_free 函數來更新全域變數 used_memory 的值,並釋放該段記憶體。

void zfree(void *ptr) {

#ifndef HAVE_MALLOC_SIZE

    void *realptr;

    size_t oldsize;

#endif

#     if (ptr == NULL) return;

# #ifdef HAVE_MALLOC_SIZE

    update_zmalloc_stat_free(zmalloc_size(ptr));

    free(ptr);

#else

#     realptr = (char*)ptr-PREFIX_SIZE;

#     oldsize = *((size_t*)realptr);

#     update_zmalloc_stat_free(oldsize PREFIX_SIZE);

    free(realptr);

#endif

# }

如下所示,這裡如果我們再來看 update_zmalloc_stat_free 函數的實作細節,你會發現它與先前的 update_zmalloc_stat_alloc 函數其執行過程類似。透過計算需要補足的記憶體位元組大小,並從 used_memory 變數中減去對應大小的記憶體空間,即可實現對記憶體空間使用率的精確計算。

#define update_zmalloc_stat_free(__n) do { \

    size_t _n = (__n); \

    if (_n&(sizeof(long)-1)) _n = sizeof(long)-(_n&(sizeof(long)-1)); \

#     atomicDecr(used_memory,__n); \

} while(0)

以上是Redis的zmalloc函數實例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
REDIS:緩存,會話管理等REDIS:緩存,會話管理等May 01, 2025 am 12:03 AM

Redis的功能主要包括緩存、會話管理和其他功能:1)緩存功能通過內存存儲數據,提高讀取速度,適用於電商網站等高頻訪問場景;2)會話管理功能在分佈式系統中共享會話數據,並通過過期時間機制自動清理;3)其他功能如發布-訂閱模式、分佈式鎖和計數器,適用於實時消息推送和多線程系統等場景。

REDIS:探索其核心功能和好處REDIS:探索其核心功能和好處Apr 30, 2025 am 12:22 AM

Redis的核心功能包括內存存儲和持久化機制。 1)內存存儲提供極快的讀寫速度,適用於高性能應用。 2)持久化通過RDB和AOF兩種方式確保數據不丟失,選擇依據應用需求。

REDIS的服務器端操作:它提供的REDIS的服務器端操作:它提供的Apr 29, 2025 am 12:21 AM

Redis'sserver-sedierations offerfunctions andTriggersForexeCutingCompleXoperationsontheserver.1)函數functionsAllowCompOustomoperationsInlua,JavaScript,javaScript,orredis'sscriptinglanguigh,增強效率和增強性。 2)

REDIS:數據庫還是服務器?揭開角色的神秘面紗REDIS:數據庫還是服務器?揭開角色的神秘面紗Apr 28, 2025 am 12:06 AM

redisisbothadatabaseandaserver.1)asadatabase,ituseSin-memorystorageforfastaccess,ifealforreal-timeapplications andCaching.2)Asaserver,ItsupportsPub/submessagingAndluAsessingandluAsessingandluascriptingftingftingftingftingftingftingftingfinteral-timecommunicationandserverserverserverserverserverserverserver-soperations。

REDIS:NOSQL方法的優勢REDIS:NOSQL方法的優勢Apr 27, 2025 am 12:09 AM

Redis是NoSQL數據庫,提供高性能和靈活性。 1)通過鍵值對存儲數據,適合處理大規模數據和高並發。 2)內存存儲和單線程模型確保快速讀寫和原子性。 3)使用RDB和AOF機制進行數據持久化,支持高可用性和橫向擴展。

REDIS:了解其架構和目的REDIS:了解其架構和目的Apr 26, 2025 am 12:11 AM

Redis是一种内存数据结构存储系统,主要用作数据库、缓存和消息代理。它的核心特点包括单线程模型、I/O多路复用、持久化机制、复制与集群功能。Redis在实际应用中常用于缓存、会话存储和消息队列,通过选择合适的数据结构、使用管道和事务、以及进行监控和调优,可以显著提升其性能。

REDIS與SQL數據庫:關鍵差異REDIS與SQL數據庫:關鍵差異Apr 25, 2025 am 12:02 AM

Redis和SQL數據庫的主要區別在於:Redis是內存數據庫,適用於高性能和靈活性需求;SQL數據庫是關係型數據庫,適用於復雜查詢和數據一致性需求。具體來說,1)Redis提供高速數據訪問和緩存服務,支持多種數據類型,適用於緩存和實時數據處理;2)SQL數據庫通過表格結構管理數據,支持複雜查詢和事務處理,適用於電商和金融系統等需要數據一致性的場景。

REDIS:它如何充當數據存儲和服務REDIS:它如何充當數據存儲和服務Apr 24, 2025 am 12:08 AM

REDISACTSASBOTHADATASTOREANDASERVICE.1)ASADATASTORE,ITUSESIN-MEMORYSTOOGATOFORFOFFASTESITION,支持VariousDatharptructuresLikeKey-valuepairsandsortedsetsetsetsetsetsetsets.2)asaservice,ItprovidespunctionslikeItionitionslikepunikeLikePublikePublikePlikePlikePlikeAndluikeAndluAascriptingiationsmpleplepleclexplectiations

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器