实验目的
测试等同序列数量,不同结构的元数据树在内存中的空间占用。
实验场景
100万时间序列
每个tag-value(MNode的name)为长度等于20的字符串
6层tag,即MTree共root节点之下共6层MNode
元数据树结构
- 第一层为StorageGroupMNode
- 倒数第二层为EntityMNode
- 最后一层为MeasurementMNode
待测元数据树结构为两种
- 节点逐层均匀扩展,即每个MNode(除叶子节点)具有相同数目的子节点,数目为10
- 序列两两之间无公共前缀,即元数据树从root往下,均为独立不交织的路径
理论分析
设时间序列数量为 N,元数据树层数为 L,每个MNode子节点数量为 Q。
在均匀扩展的场景中,由于序列由最后一层的MeasurementMNode表征,则Q^L = N;MNode节点的总量为逐层数量的累加,即一个等比数列求和,Q*(Q^L - 1)/(Q - 1) 即 Q*(N -1)/(Q - 1) 。
在序列无公共前缀的场景中,MNode节点的总量即为层数乘序列总量,即 L * N 。
则无公共前缀场景中,MNode总量为均匀扩展场景的 L * N / (N -1) * (Q - 1) / Q 倍,约 L * (Q - 1) / Q 倍(N为大数时,N / (N -1)近似为 1 )。
由于每个tag-value(MNode的name)为长度等于20的字符串,在仅考虑字符串存储的情况下,需要的存储空间为 MNode数量 * 字符串长度
均匀扩展的场景中需要 20 * Q*(N -1)/(Q - 1) 字节的存储空间,代入本次测试的数据,为 20 * 1111110, 约为22 M
无公共前缀的场景中需要 20 * Q*(N -1)/(Q - 1) 字节的存储空间,代入本次测试的数据,为 20 * 6000000, 约为120 M
在实际的实现过程中,除了最基本的字符串存储,MNode中还包含其他用于功能实现的数据结构、引用等。
单个InternalMNode大致情况如下
- name引用,8字节
- parent引用,8字节
- fullPath引用,8字节
- Map<String, IMNode> children,使用了Java的ConcurrentHashMap,额外开销较大
实验结果
每个MNode子节点数量 | MNode总量(不考虑root节点) | 内存占用总量 | |
---|---|---|---|
MNode均匀扩展 | 每个MNode有10个子节点 | 1111110 | 320M |
序列无公共前缀 | 除root节点,每个MNode仅一个子节点 | 6000000 | 1.75G |
平均每个MNode需要300字节的空间占用,即一个MNode需要300字节的空间来维护自身的属性信息以及与树结构的连接关系。
均匀扩展场景
无公共前缀场景