String 单字符串列表的内存分配率高于多字符串列表
考虑以下基准测试,它分配长度为1而不是8的字符串列表String 单字符串列表的内存分配率高于多字符串列表,string,list,scala,scala-collections,memory-consumption,String,List,Scala,Scala Collections,Memory Consumption,考虑以下基准测试,它分配长度为1而不是8的字符串列表 @State(Scope.Benchmark) @BenchmarkMode(Array(Mode.Throughput)) class SoMemory { val size = 1_000_000 @Benchmark def a: List[String] = List.fill[String](size)(Random.nextString(1)) @Benchmark def b: List[String] = List
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class SoMemory {
val size = 1_000_000
@Benchmark def a: List[String] = List.fill[String](size)(Random.nextString(1))
@Benchmark def b: List[String] = List.fill[String](size)(Random.nextString(8))
}
其中sbt jmh:run-i10-wi10-f2-t1-prof gc bench.SoMemory给出
请注意,较小的字符串具有显著较高的gc.alloc.rate
举例来说,当字符串越小,内存占用越小时,为什么在第一种情况下内存消耗越高
class ZarA { val x = List.fill[String](1_000_000)(Random.nextString(1)) }
class ZarB { val x = List.fill[String](1_000_000)(Random.nextString(8)) }
正如所料,ZarA的占地面积较小,约为72MB
相比之下,ZarB的占地面积更大,约为80MB
视觉记忆行为
ZarA-使用了129MB的堆
ZarB-使用堆91 MB
分配速率是指分配内存的速度,即每单位时间分配的内存量。它没有告诉我们任何关于总内存分配的信息
找到更小的连续内存区域总是比找到更大的连续内存区域更容易,因此,例如,分配长度为1的1000个字符串比分配长度为8的1000个字符串花费的时间要少,导致更高的分配率和更少的总内存消耗。分配率是指您可以以多快的速度分配每单位时间分配的内存量。它没有告诉我们任何关于总内存分配的信息
找到更小的连续内存区域总是比找到更大的连续内存区域更容易,因此,例如,分配长度为1的1000个字符串比分配长度为8的1000个字符串花费的时间要少,导致更高的分配率和更少的总内存消耗。使用似乎表明ZarA消耗更多的总内存。更高的gc.alloc.rate.norm是否表示更高的总内存消耗?norm代表规范化,但它仍然是速率速度,而不是总体分配。这两个JMH mertics都没有告诉我们内存的总使用量,我认为JMH不是衡量内存消耗的合适工具。对于这一点,一些剖析器会更好。从运行时打印内存会告诉您某个时间点的内存使用情况,我们不知道它是在GC之前还是在分析器可以强制GC为我们提供更清晰的图片之后,所以我认为它可能只是作为内存使用直方图的输入才有意义。尝试强制GC并查看分配对象的列表,这应该告诉你一些有趣的事情。在使用System.GC强制GC之后,ZarA案例的堆使用量约为75 MB,而ZarB案例的堆使用量约为85 MB,这确实与JOL预测类似。谢谢,这澄清了它。使用似乎表明ZarA消耗了更多的总内存。更高的gc.alloc.rate.norm是否表示更高的总内存消耗?norm代表规范化,但它仍然是速率速度,而不是总体分配。这两个JMH mertics都没有告诉我们内存的总使用量,我认为JMH不是衡量内存消耗的合适工具。对于这一点,一些剖析器会更好。从运行时打印内存会告诉您某个时间点的内存使用情况,我们不知道它是在GC之前还是在分析器可以强制GC为我们提供更清晰的图片之后,所以我认为它可能只是作为内存使用直方图的输入才有意义。尝试强制GC并查看分配对象的列表,这应该告诉你一些有趣的事情。在使用System.GC强制GC之后,ZarA案例的堆使用量约为75 MB,而ZarB案例的堆使用量约为85 MB,这确实与JOL预测类似。谢谢,这就澄清了。
SoMemory.a:·gc.alloc.rate thrpt 20 3870.364 ± 120.687 MB/sec
SoMemory.b:·gc.alloc.rate thrpt 20 2763.961 ± 89.654 MB/sec
class ZarA { val x = List.fill[String](1_000_000)(Random.nextString(1)) }
class ZarB { val x = List.fill[String](1_000_000)(Random.nextString(8)) }
example.ZarA@15975490d footprint:
COUNT AVG SUM DESCRIPTION
1000000 24 24000000 [C
1 16 16 example.ZarA
1000000 24 24000000 java.lang.String
1000000 24 24000000 scala.collection.immutable.$colon$colon
1 16 16 scala.collection.immutable.Nil$
3000002 72000032 (total)
example.ZarB@15975490d footprint:
COUNT AVG SUM DESCRIPTION
1000000 32 32000000 [C
1 16 16 example.ZarB
1000000 24 24000000 java.lang.String
1000000 24 24000000 scala.collection.immutable.$colon$colon
1 16 16 scala.collection.immutable.Nil$
3000002 80000032 (total)