162306a36Sopenharmony_ci:Original: Documentation/mm/zsmalloc.rst
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci:翻译:
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci 司延腾 Yanteng Si <siyanteng@loongson.cn>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci:校译:
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci========
1062306a36Sopenharmony_cizsmalloc
1162306a36Sopenharmony_ci========
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci这个分配器是为与zram一起使用而设计的。因此,该分配器应该在低内存条件下工作良好。特别是,
1462306a36Sopenharmony_ci它从未尝试过higher order页面的分配,这在内存压力下很可能会失败。另一方面,如果我们只
1562306a36Sopenharmony_ci是使用单(0-order)页,它将遭受非常高的碎片化 - 任何大小为PAGE_SIZE/2或更大的对象将
1662306a36Sopenharmony_ci占据整个页面。这是其前身(xvmalloc)的主要问题之一。
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci为了克服这些问题,zsmalloc分配了一堆0-order页面,并使用各种"struct page"字段将它
1962306a36Sopenharmony_ci们链接起来。这些链接的页面作为一个单一的higher order页面,即一个对象可以跨越0-order
2062306a36Sopenharmony_ci页面的边界。代码将这些链接的页面作为一个实体,称为zspage。
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci为了简单起见,zsmalloc只能分配大小不超过PAGE_SIZE的对象,因为这满足了所有当前用户的
2362306a36Sopenharmony_ci要求(在最坏的情况下,页面是不可压缩的,因此以"原样"即未压缩的形式存储)。对于大于这
2462306a36Sopenharmony_ci个大小的分配请求,会返回失败(见zs_malloc)。
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci此外,zs_malloc()并不返回一个可重复引用的指针。相反,它返回一个不透明的句柄(无符号
2762306a36Sopenharmony_ci长),它编码了被分配对象的实际位置。这种间接性的原因是zsmalloc并不保持zspages的永久
2862306a36Sopenharmony_ci映射,因为这在32位系统上会导致问题,因为内核空间映射的VA区域非常小。因此,在使用分配
2962306a36Sopenharmony_ci的内存之前,对象必须使用zs_map_object()进行映射以获得一个可用的指针,随后使用
3062306a36Sopenharmony_cizs_unmap_object()解除映射。
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistat
3362306a36Sopenharmony_ci====
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci通过CONFIG_ZSMALLOC_STAT,我们可以通过 ``/sys/kernel/debug/zsmalloc/<user name>``
3662306a36Sopenharmony_ci看到zsmalloc内部信息。下面是一个统计输出的例子。::
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci # cat /sys/kernel/debug/zsmalloc/zram0/classes
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage
4162306a36Sopenharmony_ci    ...
4262306a36Sopenharmony_ci    ...
4362306a36Sopenharmony_ci     9   176           0            1           186        129          8                4
4462306a36Sopenharmony_ci    10   192           1            0          2880       2872        135                3
4562306a36Sopenharmony_ci    11   208           0            1           819        795         42                2
4662306a36Sopenharmony_ci    12   224           0            1           219        159         12                4
4762306a36Sopenharmony_ci    ...
4862306a36Sopenharmony_ci    ...
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciclass
5262306a36Sopenharmony_ci	索引
5362306a36Sopenharmony_cisize
5462306a36Sopenharmony_ci	zspage存储对象大小
5562306a36Sopenharmony_cialmost_empty
5662306a36Sopenharmony_ci	ZS_ALMOST_EMPTY zspage的数量(见下文)。
5762306a36Sopenharmony_cialmost_full
5862306a36Sopenharmony_ci	ZS_ALMOST_FULL zspage的数量(见下图)
5962306a36Sopenharmony_ciobj_allocated
6062306a36Sopenharmony_ci	已分配对象的数量
6162306a36Sopenharmony_ciobj_used
6262306a36Sopenharmony_ci	分配给用户的对象的数量
6362306a36Sopenharmony_cipages_used
6462306a36Sopenharmony_ci	为该类分配的页数
6562306a36Sopenharmony_cipages_per_zspage
6662306a36Sopenharmony_ci	组成一个zspage的0-order页面的数量
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci当n <= N / f时,我们将一个zspage分配给ZS_ALMOST_EMPTYfullness组,其中
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci* n = 已分配对象的数量
7162306a36Sopenharmony_ci* N = zspage可以存储的对象总数
7262306a36Sopenharmony_ci* f = fullness_threshold_frac(即,目前是4个)
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci同样地,我们将zspage分配给:
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci* ZS_ALMOST_FULL  when n > N / f
7762306a36Sopenharmony_ci* ZS_EMPTY        when n == 0
7862306a36Sopenharmony_ci* ZS_FULL         when n == N
79