长亭百川云 - 文章详情

解密 bytes 对象的缓存池

古明地觉的编程教室

41

2024-07-13

bytes 对象是不可变对象,那么根据我们对浮点数的了解,可以大胆猜测 bytes 对象也有自己的缓存池。

// Include/internal/pycore_global_objects.h  
struct _Py_static_objects {  
    struct {  
        // 该结构体保存了一些静态分配的对象,它们都是单例的  
        // 小整数对象池  
        PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];  
        // 空的 bytes 对象  
        PyBytesObject bytes_empty;  
        // bytes 对象缓存池  
        struct {  
            PyBytesObject ob;  
            char eos;  
        } bytes_characters[256];  
        // ...  
    } singletons;  
};

结构体里的 bytes_characters 便是 bytes 对象的缓存池,这是一个长度为 256 的数组,这意味着缓存池里面可以容纳 256 个 bytes 对象。

但 _Py_static_objects 保存的是静态分配的单例对象,也就是说在解释器启动之后这些对象就已经被初始化好了,所以 bytes 对象缓存池和小整数对象池一样,里面存储的对象是固定的。

小整数对象池里面存储的是 -5 ~ 256 之间的整数,而 bytes 对象缓存池里面存储的是 256 个单字节 bytes 对象,即 b"\x00"、b"\x01"、····、b"\xff"。所以解释器对长度为 1 的 bytes 对象是做了优化的,它们只会存在一份,因为一个字节的最大值为 255,所以 bytes_characters 里面保存了 256 个 bytes 对象。

当然以上都只是结论,我们来实际看一下初始化的过程。

// Include/internal/pycore_runtime_init.h  
#define _PyRuntimeState_INIT(runtime) \  
    { \  
     /* ... */ \  
        .static_objects = { \  
            .singletons = { \  
                .small_ints = _Py_small_ints_INIT, \  
                .bytes_empty = _PyBytes_SIMPLE_INIT(0, 0), \  
                .bytes_characters = _Py_bytes_characters_INIT, \  
            }, \  
        }, \  
        ._main_interpreter = \  
            _PyInterpreterState_INIT(runtime._main_interpreter), \  
    }

runtime 保存了程序运行时的环境和行为,比如内存分配、异常处理、GIL 状态、以及静态单例对象等等,当然还有进程状态对象。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2