zoukankan      html  css  js  c++  java
  • Python int 数据数据类型在内存中分配原理

    python代码如下

    import sys
    for i in "abcdefghijkdfasdf;;lblcv":
        byte_list = bytes(i, encoding="utf-8")
        print('*' * 11, byte_list)
        for k in byte_list:
            print(type(k))
            print(sys.getsizeof(k))
            # print(bin(k))
            print(hex(id(k)))
    

      bytes函数将字符串按照encoding 将字符串转换为字节序列;

          utf-8中一个英文字母占1个字节

     执行结果

     关于内存地址的理解如下

    电脑的内存(尤其是指主存)是由许多“内存地址”所组成的,每个内存地址都有一个“物理地址”,能供CPU(或其他设备)访问。一般,只有如BIOS操作系统及部分特定之公用软件(如内存测试软件)等系统软件,能使用机器码的运算对象或寄存器对物理地址定址,指示CPU要求内存控制器之类的硬件设备,使用内存总线或系统总线,亦或分别之控制总线地址总线数据总线,运行该程序之命令。内存控制器的总线是由数条并行的线路所组成的,每条线路表示一个比特。总线的宽度因此依电脑不同,决定了可定址之存储单位数量,以及每一单位内的比特数量。
    计算机程序使用内存地址来运行机器码、存储及截取数据。大多数的应用程序无法得知实际的物理地址,而是使用电脑的内存管理单元及操作系统的内存映射,为“逻辑地址”或虚拟地址定址
     
    内存地址0x0001和内存地址0x0002之间差的是一个byte,而不是一个bit?
    下内存的物理构造,一般内存的外形图片如图1。一个内存是由若干个黑色的内存颗粒构成的。每一个内存颗粒叫做一个chip。
     
    图1.内存外形图
    上面这个内存条有8个chip。每一个chip内部,是由8个bank组成的。其构造如下图:
     
    图2.内存颗粒物理结构
    在每个bank内部,就是电容的行列矩阵结构了。(注意,二维矩阵中的一个元素一般存储着8个bit,也就是说包含了8个小电容)。
     
    图3.bank物理结构

    8个同位置的元素,一起组成在内存中连续的64个bit。如下图
     
    图4.jpg

    通过内存的物理结构我们可以看出,因为在内存中最小单位就是字节。所以操作系统在管理它的时候,最小单位也就是字节了。另外,通过上述的我们还有一个额外发现。那就是在内存中连续的64个bit,其实在内存的物理结构中,并不连续。而是分散在同位置的8个rank上的。

    计算机的存储空间比作一本空白的短篇小说。页面上还没有任何内容。最终,会有不同的作者出现。每个作者都需要一些空间来写他们的故事。

    由于不允许彼此书写,因此必须注意他们能书写的页面。开始书写之前,请先咨询书籍管理员。然后,管理员决定允许他们在书中写什么。

    如果这书已经存在很长时间了,因此其中的许多故事都不再适用。当没有人阅读或引用故事时,它们将被删除以为新故事腾出空间。

    本质上,计算机内存就像一本空书。实际上,调用固定长度的连续内存面块是很常见的,因此这种类比非常适用。

    作者就像需要将数据存储在内存中的不同应用程序或进程。决定作者在书中书写位置的管理员就像是各种存储器管理的角色,删除旧故事为新故事腾出空间的人是垃圾收集者(garbage collector)。

    内存管理是应用程序读取和写入数据的过程。内存管理器确定将应用程序数据放置在何处。

    由于内存有限,类比书中的页面一样,管理员必须找到一些可用空间并将其提供给应用程序。提供内存的过程通常称为内存分配。

    其实如果我们了解内存管理机制,以更快、更好的方式解决问题。

    Python 语音中 一切皆对象,Python对象实现的核心就是一个结构体--PyObject

    PyObject是每个对象必有的内容,可以说是Python中所有对象的祖父,仅包含两件事:

    • ob_refcnt:引用计数(reference count)
    • ob_type:指向另一种类型的指针(pointer to another type)

    Python将部分内存用于内部使用和非对象内存。另一部分专用于对象存储(您的int,dict等)

    Python的内存分配器

    内存结构

    在Python中,当要分配内存空间时,不单纯使用 malloc/free,而是在其基础上堆放3个独立的分层,有效率地进行分配。

    [图片上传失败...(image-22ef57-1588088246750)]
    第 0 层往下是 OS 的功能。第 -2 层是隐含和机器的物理性相关联的部分,OS 的虚拟内 存管理器负责这部分功能。第 -1 层是与机器实际进行交互的部分,OS 会执行这部分功能。 因为这部分的知识已经超出了本书的范围,我们就不额外加以说明了。
    在第 3 层到第 0 层调用了一些具有代表性的函数,其调用图如下。
    [图片上传失败...(image-8142ba-1588088246750)]

    第0层 通用的基础分配器

    以 Linux 为例,第 0 层指的就是 glibc 的 malloc() 这样的分配器,是对 Linux 等 OS 申 请内存的部分。

    Python 中并不是在生成所有对象时都调用 malloc(),而是根据要分配的内存大小来改 变分配的方法。申请的内存大小如果大于 256 字节,就老实地调用 malloc();如果小于等 于 256 字节,就要轮到第 1 层和第 2 层出场了

    第1层处理的信息的内存结构

    根据所管理的内存空间的作用和大小的不同,我们称最小 的单位为 block,最终返回给申请者的就是这个 block 的地址。比 block 大的单位的是 pool, pool 内部包含 block。pool 再往上叫作 arena。

    也就是说 arena > pool > block,感觉很像俄罗斯套娃吧。
    为了避免频繁调用 malloc() 和 free(),第 0 层的分配器会以最大的单位 arena 来保留 内存。pool 是用于有效管理空的 block 的单位。
    arena 这个词有“竞技场”的意思。大家可以理解成竞技场里有很多个 pool,pool 里面漂 浮着很多个 block,这样或许更容易理解一些。

    arena

    Arenas是最大的内存块,并在内存中的页面边界上对齐。页面边界是操作系统使用的固定长度连续内存块的边缘。Python假设系统的页面大小为256 KB。
    [图片上传失败...(image-e2e369-1588088246750)]
    Arenas内有内存池,池是一个虚拟内存页(4 KB)。这些就像我们书中类比的页面。这些池被分成较小的内存块。

    给定池中的所有块均具有相同的“大小等级”。给定一定数量的请求数据,大小类定义特定的块大小。

    第1层总结

    第 1 层的任务可以用一句话来总结,那就是“管理 arena”。

    第2层 Python对象分配器

    第 2 层的分配器负责管理 pool 内的 block。

    block

    pool 被分割成一个个的 block。我们在 Python 中生成对象时,最终都会被分配这个 block (在要求大小不大于 256 字节的情况下)。
    以 block 为单位来划分,这是从 pool 初始化时就决定好的。这是因为我们一开始利用 pool 的时候就决定了“这是供 8 字节的 block 使用的 pool”。
    pool 内被 block 完全填满了,那么 pool 是怎么进行 block 的状态管理的呢?
    block 只有以下三种状态。

    1. 已经分配
    2. 使用完毕
    3. 未使用

    第3层 对象特有的分配器

    对象有列表和元组等多种多样的型,在生成它们的时候要使用各自特有的分配器。

    分配器的总结



    一个内存地址所代表的永远是1个字节,内存的每一个字节都有为一个个编号

    字节是计算机中数据处理的基本单位;1个字节=8个bit

     内存地址只是一个编号,代表一个内存空间;

    内存地址所执行的内存单元大小就是1字节,跟内存地址位数无关;

    内存空间大小就是寻址能力,即能访问到多少个地址

    int在python里是一个类,是不可变数据类型中的一种,一些性质和字符串是一样的,是整型

    32位系统
    int:开销= 10字节,值= 4字节
    float:开销= 8字节,value = 8字节
    
    64位系统
    int:开销= 20字节,值= 8字节
    float:开销= 16个字节,值= 8个字节

    因此,sys.getsizeof(0) 数组元素为0。此时占用24字节(PyObject_VAR_HEAD 的大小)。 sys.getsizeof(456) 需使用一个元素,因此多了4个字节。

    综上,一个int类型占用了28字节,根据内存分配原则,计算机分配了32字节的内存空间

  • 相关阅读:
    django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
    Error fetching command 'collectstatic': You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path. Command 'collectstatic' skipped
    windows 虚拟环境下 安装 mysql 引擎一系列错误处理
    项目概念流程
    pip 使用
    HTTPserver v3.0 版本项目
    GitHub 使用
    git 操作命令详解
    git 忽略部分文件类型的同步
    Python 正则处理_re模块
  • 原文地址:https://www.cnblogs.com/workherd/p/14199648.html
Copyright © 2011-2022 走看看