我一直在尝试了解有关在Scala中选择Seq或List的基本原理,为了帮助实现这一点,我试图创建一个简单的定时示例,在其中创建每个实例的实例,并用相同的实例填充元素数量-见下文。
object SeqVsList extends App with LazyLogging {
private val numberOfElements = 1234567
// whichever of these is run first takes the most amount of time
populateSeq()
populateList()
def populateSeq(): Unit = {
val seqStartTime = System.currentTimeMillis()
val aSeq = Seq.fill(numberOfElements)("foo")
logger.info(s"Populating Seq took ${System.currentTimeMillis() - seqStartTime} ms")
}
def populateList(): Unit = {
val listStartTime = System.currentTimeMillis()
val aList = List.fill(numberOfElements)("bar")
logger.info(s"Populating List took ${System.currentTimeMillis() - listStartTime} ms")
}
}
我遇到的问题(如代码中的注释所定义)是该示例无法准确表示哪个元素填充所有元素的最快,而是我首先调用的方法总是最慢的。 / p>
我想象幕后有什么事情发生,例如在运行时将一堆对象加载到内存中,这会减慢这两种方法中的第一种的速度?如果有人可以帮助我对此有所了解,我将非常感激。
答案 0 :(得分:1)
我刚刚尝试通过 sbt-jmh 进行一些基准测试来证明Seq和List相等的想法:
package bmks
import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations.{Benchmark, OutputTimeUnit}
@OutputTimeUnit(TimeUnit.MILLISECONDS)
class TestBenchmark {
@Benchmark
def seq(): Seq[String] =
Seq.fill(1234567)("foo")
@Benchmark
def list(): Seq[String] =
List.fill(1234567)("foo")
}
运行:
$ sbt
$ sbt:benchmarks> jmh:run -i 20 -wi 10 -f1 -t1
并得到:
sbt:benchmarks> jmh:run -i 20 -wi 10 -f1 -t1
[info] Compiling 1 Scala source to /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/classes ...
[info] Done compiling.
[info] Packaging /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/benchmarks_2.12-1.0.jar ...
Processing 1 classes from /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/classes with "reflection" generator
Writing out Java source to /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/src_managed/jmh and resources to /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/resource_managed/jmh
[info] Done packaging.
[info] Compiling 6 Java sources to /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/classes ...
[info] Done compiling.
[info] Packaging /Volumes/AuroraHD/DEV/scala/benchmarks/target/scala-2.12/benchmarks_2.12-1.0-jmh.jar ...
[info] Done packaging.
[info] Running (fork) org.openjdk.jmh.Main -i 20 -wi 10 -f1 -t1
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_161, Java HotSpot(TM) 64-Bit Server VM, 25.161-b12
[info] # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 10 iterations, 10 s each
[info] # Measurement: 20 iterations, 10 s each
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread, will synchronize iterations
[info] # Benchmark mode: Throughput, ops/time
[info] # Benchmark: bmks.TestBenchmark.list
[info] # Run progress: 0.00% complete, ETA 00:10:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration 1: 0.091 ops/ms
[info] # Warmup Iteration 2: 0.111 ops/ms
[info] # Warmup Iteration 3: 0.111 ops/ms
[info] # Warmup Iteration 4: 0.113 ops/ms
[info] # Warmup Iteration 5: 0.112 ops/ms
[info] # Warmup Iteration 6: 0.115 ops/ms
[info] # Warmup Iteration 7: 0.114 ops/ms
[info] # Warmup Iteration 8: 0.116 ops/ms
[info] # Warmup Iteration 9: 0.115 ops/ms
[info] # Warmup Iteration 10: 0.115 ops/ms
[info] Iteration 1: 0.115 ops/ms
[info] Iteration 2: 0.116 ops/ms
[info] Iteration 3: 0.114 ops/ms
[info] Iteration 4: 0.114 ops/ms
[info] Iteration 5: 0.115 ops/ms
[info] Iteration 6: 0.114 ops/ms
[info] Iteration 7: 0.116 ops/ms
[info] Iteration 8: 0.115 ops/ms
[info] Iteration 9: 0.115 ops/ms
[info] Iteration 10: 0.115 ops/ms
[info] Iteration 11: 0.115 ops/ms
[info] Iteration 12: 0.115 ops/ms
[info] Iteration 13: 0.114 ops/ms
[info] Iteration 14: 0.116 ops/ms
[info] Iteration 15: 0.115 ops/ms
[info] Iteration 16: 0.115 ops/ms
[info] Iteration 17: 0.115 ops/ms
[info] Iteration 18: 0.114 ops/ms
[info] Iteration 19: 0.114 ops/ms
[info] Iteration 20: 0.117 ops/ms
[info] Result "bmks.TestBenchmark.list":
[info] 0.115 ±(99.9%) 0.001 ops/ms [Average]
[info] (min, avg, max) = (0.114, 0.115, 0.117), stdev = 0.001
[info] CI (99.9%): [0.114, 0.116] (assumes normal distribution)
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_161, Java HotSpot(TM) 64-Bit Server VM, 25.161-b12
[info] # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 10 iterations, 10 s each
[info] # Measurement: 20 iterations, 10 s each
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread, will synchronize iterations
[info] # Benchmark mode: Throughput, ops/time
[info] # Benchmark: bmks.TestBenchmark.seq
[info] # Run progress: 50.00% complete, ETA 00:05:01
[info] # Fork: 1 of 1
[info] # Warmup Iteration 1: 0.094 ops/ms
[info] # Warmup Iteration 2: 0.115 ops/ms
[info] # Warmup Iteration 3: 0.118 ops/ms
[info] # Warmup Iteration 4: 0.115 ops/ms
[info] # Warmup Iteration 5: 0.114 ops/ms
[info] # Warmup Iteration 6: 0.115 ops/ms
[info] # Warmup Iteration 7: 0.115 ops/ms
[info] # Warmup Iteration 8: 0.115 ops/ms
[info] # Warmup Iteration 9: 0.114 ops/ms
[info] # Warmup Iteration 10: 0.117 ops/ms
[info] Iteration 1: 0.116 ops/ms
[info] Iteration 2: 0.116 ops/ms
[info] Iteration 3: 0.089 ops/ms
[info] Iteration 4: 0.116 ops/ms
[info] Iteration 5: 0.116 ops/ms
[info] Iteration 6: 0.118 ops/ms
[info] Iteration 7: 0.116 ops/ms
[info] Iteration 8: 0.118 ops/ms
[info] Iteration 9: 0.118 ops/ms
[info] Iteration 10: 0.117 ops/ms
[info] Iteration 11: 0.117 ops/ms
[info] Iteration 12: 0.107 ops/ms
[info] Iteration 13: 0.111 ops/ms
[info] Iteration 14: 0.113 ops/ms
[info] Iteration 15: 0.113 ops/ms
[info] Iteration 16: 0.114 ops/ms
[info] Iteration 17: 0.114 ops/ms
[info] Iteration 18: 0.114 ops/ms
[info] Iteration 19: 0.114 ops/ms
[info] Iteration 20: 0.114 ops/ms
[info] Result "bmks.TestBenchmark.seq":
[info] 0.114 ±(99.9%) 0.005 ops/ms [Average]
[info] (min, avg, max) = (0.089, 0.114, 0.118), stdev = 0.006
[info] CI (99.9%): [0.108, 0.119] (assumes normal distribution)
[info] # Run complete. Total time: 00:10:02
[info] REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
[info] why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
[info] experiments, perform baseline and negative tests that provide experimental control, make sure
[info] the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
[info] Do not assume the numbers tell you what you want them to tell.
[info] Benchmark Mode Cnt Score Error Units
[info] TestBenchmark.list thrpt 20 0.115 ± 0.001 ops/ms
[info] TestBenchmark.seq thrpt 20 0.114 ± 0.005 ops/ms
[success] Total time: 607 s, completed Apr 29, 2019 8:35:22 PM
结论:它们是相等的。