欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python?虛擬機(jī)字典dict內(nèi)存優(yōu)化方法解析

 更新時(shí)間:2023年03月26日 08:49:03   作者:一無是處的研究僧  
這篇文章主要為大家介紹了Python?虛擬機(jī)字典dict內(nèi)存優(yōu)化方法解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

在前面的文章當(dāng)中我們討論的是 python3 當(dāng)中早期的內(nèi)嵌數(shù)據(jù)結(jié)構(gòu)字典的實(shí)現(xiàn),在本篇文章當(dāng)中主要介紹在后續(xù)對(duì)于字典的內(nèi)存優(yōu)化。

字典優(yōu)化

在前面的文章當(dāng)中我們介紹的字典的數(shù)據(jù)結(jié)構(gòu)主要如下所示:

typedef struct {
    PyObject_HEAD
    Py_ssize_t ma_used;
    PyDictKeysObject *ma_keys;
    PyObject **ma_values;
} PyDictObject;
struct _dictkeysobject {
    Py_ssize_t dk_refcnt;
    Py_ssize_t dk_size;
    dict_lookup_func dk_lookup;
    Py_ssize_t dk_usable;
    PyDictKeyEntry dk_entries[1];
};
typedef struct {
    /* Cached hash code of me_key. */
    Py_hash_t me_hash;
    PyObject *me_key;
    PyObject *me_value; /* This field is only meaningful for combined tables */
} PyDictKeyEntry;

用圖示的方式表示如下圖所示:

所有的鍵值對(duì)都存儲(chǔ)在 dk_entries 數(shù)組當(dāng)中,比如對(duì)于 "Hello" "World" 這個(gè)鍵值對(duì)存儲(chǔ)過程如下所示,如果 "Hello" 的哈希值等于 8 ,那么計(jì)算出來對(duì)象在 dk_entries 數(shù)組當(dāng)中的下標(biāo)位 0 。

在前面的文章當(dāng)中我們談到了,在 cpython 當(dāng)中 dk_entries 數(shù)組當(dāng)中的一個(gè)對(duì)象占用 24 字節(jié)的內(nèi)存空間,在 cpython 當(dāng)中的負(fù)載因子是 23\frac{2}{3}32? 。而一個(gè) entry 的大小是 24 個(gè)字節(jié),如果 dk_entries 的長(zhǎng)度是 1024 的話,那么大概有 1024 / 3 * 24 = 8K 的內(nèi)存空間是浪費(fèi)的。為了解決這個(gè)問題,在新版的 cpython 當(dāng)中采取了一個(gè)策略用于減少內(nèi)存的使用。具體的設(shè)計(jì)如下圖所示:

在新的字典當(dāng)中 cpython 對(duì)于 dk_entries 來說如果正常的哈希表的長(zhǎng)度為 8 的話,因?yàn)樨?fù)載因子是 23\frac{2}{3}32? 真正給 dk_entries 分配的長(zhǎng)度是 5 = 8 / 3,那么現(xiàn)在有一個(gè)問題就是如何根據(jù)不同的哈希值進(jìn)行對(duì)象的存儲(chǔ)。dk_indices 就是這個(gè)作用的,他的長(zhǎng)度和真正的哈希表的長(zhǎng)度是一樣的,dk_indices 是一個(gè)整型數(shù)組這個(gè)數(shù)組保存的是要保存對(duì)象在 dk_entries 當(dāng)中的下標(biāo),比如在上面的例子當(dāng)中 dk_indices[7] = 0,就表示哈希值求余數(shù)之后的值等于 7,0 表示對(duì)象在 dk_entries 當(dāng)中的下標(biāo)。

現(xiàn)在我們?cè)俨迦胍粋€(gè)數(shù)據(jù) "World" "Hello" 鍵值對(duì),假設(shè) "World" 的哈希值等于 8,那么對(duì)哈希值求余數(shù)之后等于 0 ,那么 dk_indices[0] 就是保存對(duì)象在 dk_entries 數(shù)組當(dāng)中的下標(biāo)的,圖中對(duì)應(yīng)的下標(biāo)為 1 (因?yàn)?dk_entries 數(shù)組當(dāng)中的每個(gè)數(shù)據(jù)都要使用,因此直接遞增即可,下一個(gè)對(duì)象來的話就保存在 dk_entries 數(shù)組的第 3 個(gè)(下標(biāo)為 2)位置)。

內(nèi)存分析

首先我們先來分析一下數(shù)組 dk_indices 的數(shù)據(jù)類型,在 cpython 的內(nèi)部實(shí)現(xiàn)當(dāng)中并沒有一刀切的直接將這個(gè)數(shù)組當(dāng)中的數(shù)據(jù)類型設(shè)置成 int 類型。

dk_indices 數(shù)組主要有以下幾個(gè)類型:

  • 當(dāng)哈希表長(zhǎng)度小于 0xff 時(shí),dk_indices 的數(shù)據(jù)類型為 int8_t ,即一個(gè)元素值占一個(gè)字節(jié)。
  • 當(dāng)哈希表長(zhǎng)度小于 0xffff 時(shí),dk_indices 的數(shù)據(jù)類型為 int16_t ,即一個(gè)元素值占 2 一個(gè)字節(jié)。
  • 當(dāng)哈希表長(zhǎng)度小于 0xffffffff 時(shí),dk_indices 的數(shù)據(jù)類型為 int32_t ,即一個(gè)元素值占 4 個(gè)字節(jié)。
  • 當(dāng)哈希表長(zhǎng)度大于 0xffffffff 時(shí),dk_indices 的數(shù)據(jù)類型為 int64_t ,即一個(gè)元素值占 8 個(gè)字節(jié)。

與這個(gè)相關(guān)的代碼如下所示:

/* lookup indices.  returns DKIX_EMPTY, DKIX_DUMMY, or ix >=0 */
static inline Py_ssize_t
dictkeys_get_index(const PyDictKeysObject *keys, Py_ssize_t i)
{
    Py_ssize_t s = DK_SIZE(keys);
    Py_ssize_t ix;
    if (s <= 0xff) {
        const int8_t *indices = (const int8_t*)(keys->dk_indices);
        ix = indices[i];
    }
    else if (s <= 0xffff) {
        const int16_t *indices = (const int16_t*)(keys->dk_indices);
        ix = indices[i];
    }
#if SIZEOF_VOID_P > 4
    else if (s > 0xffffffff) {
        const int64_t *indices = (const int64_t*)(keys->dk_indices);
        ix = indices[i];
    }
#endif
    else {
        const int32_t *indices = (const int32_t*)(keys->dk_indices);
        ix = indices[i];
    }
    assert(ix >= DKIX_DUMMY);
    return ix;
}

現(xiàn)在來分析一下相關(guān)的內(nèi)存使用情況:

哈希表長(zhǎng)度能夠保存的鍵值對(duì)數(shù)目老版本新版本節(jié)約內(nèi)存量(字節(jié))
256256 * 2 / 3 = 17024 * 256 = 61441 * 256 + 24 * 170 = 43361808
6553665536 * 2 / 3 = 4369024 * 65536 = 15728642 * 65536 + 24 * 43690 = 1179632393232

從上面的表格我們可以看到哈希表的長(zhǎng)度越大我們節(jié)約的內(nèi)存就越大,優(yōu)化的效果就越明顯。

總結(jié)

在本篇文章當(dāng)中主要介紹了在 python3 當(dāng)中對(duì)于字典的優(yōu)化操作,主要是通過一個(gè)內(nèi)存占用量比較小的數(shù)組去保存鍵值對(duì)在真實(shí)保存鍵值對(duì)當(dāng)中的下標(biāo)實(shí)現(xiàn)的,這個(gè)方法對(duì)于節(jié)約內(nèi)存的效果是非常明顯的。

本篇文章是深入理解 python 虛擬機(jī)系列文章之一,

文章地址:github.com/Chang-LeHun…

更多精彩內(nèi)容合集可訪問項(xiàng)目:github.com/Chang-LeHun…

以上就是Python 虛擬機(jī)字典dict的優(yōu)化方法解析的詳細(xì)內(nèi)容,更多關(guān)于Python 虛擬機(jī)字典dict優(yōu)化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Python語法之模塊Module

    詳解Python語法之模塊Module

    這篇文章主要為大家介紹了Python語法之模塊Module,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • python使用requests實(shí)現(xiàn)發(fā)送帶文件請(qǐng)求功能

    python使用requests實(shí)現(xiàn)發(fā)送帶文件請(qǐng)求功能

    這篇文章主要介紹了python使用requests實(shí)現(xiàn)發(fā)送帶文件請(qǐng)求,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • python中類變量與成員變量的使用注意點(diǎn)總結(jié)

    python中類變量與成員變量的使用注意點(diǎn)總結(jié)

    python 的類中主要會(huì)使用的兩種變量:類變量與成員變量。類變量是類所有實(shí)例化對(duì)象共有的,而成員變量是每個(gè)實(shí)例化對(duì)象自身特有的。下面這篇文章主要給大家介紹了在python中類變量與成員變量的一些使用注意點(diǎn),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-04-04
  • 一文搞定Scrapy和Selenium整合使用

    一文搞定Scrapy和Selenium整合使用

    Scrapy和Selenium都是常用的Python爬蟲框架,下面這篇文章主要給大家介紹了關(guān)于如何通過一文搞定Scrapy和Selenium整合使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Pandas Describe函數(shù)的具體使用

    Pandas Describe函數(shù)的具體使用

    在Pandas中,describe()能夠?yàn)閿?shù)據(jù)框中的數(shù)值列提供統(tǒng)計(jì)摘要信息,本文主要介紹了Pandas Describe函數(shù)的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • Python實(shí)現(xiàn)腳本轉(zhuǎn)換為命令行程序

    Python實(shí)現(xiàn)腳本轉(zhuǎn)換為命令行程序

    使用Python中的scaffold和click庫,你可以將一個(gè)簡(jiǎn)單的實(shí)用程序升級(jí)為一個(gè)成熟的命令行界面工具,本文就來帶你看看具體實(shí)現(xiàn)方法,感興趣的可以了解下
    2022-09-09
  • Python進(jìn)階之如何快速將變量插入有序數(shù)組

    Python進(jìn)階之如何快速將變量插入有序數(shù)組

    在我們學(xué)習(xí)python的過程中,學(xué)習(xí)序列是一門必修課。本文我們就來一起看一看Python是如何快速將變量插入有序數(shù)組的,感興趣的可以了解一下
    2023-04-04
  • Python操作SQLite數(shù)據(jù)庫過程解析

    Python操作SQLite數(shù)據(jù)庫過程解析

    這篇文章主要介紹了Python操作SQLite數(shù)據(jù)庫過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Python必備技能之debug調(diào)試教程詳解

    Python必備技能之debug調(diào)試教程詳解

    這篇文章主要為大家詳細(xì)介紹了Python初學(xué)者必須要學(xué)會(huì)的技能——在Python中進(jìn)行debug操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-03-03
  • 3段Python圖像處理的實(shí)用代碼的分享

    3段Python圖像處理的實(shí)用代碼的分享

    這篇文章主要介紹了3段Python圖像處理的實(shí)用代碼的分享,計(jì)算機(jī)視覺方向的Python實(shí)用代碼,用到多種庫具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-06-06

最新評(píng)論