Открытый выпуск Enumeratum EnumSet / EnumMap # 113 дает информативный тест
[info] MapComparisons.enumeratumScalaMapGet avgt 30 9.830 ± 0.207 ns/op
[info] MapComparisons.jEnumEnumMapGet avgt 30 4.745 ± 0.685 ns/op
[info] MapComparisons.jEnumScalaMapGet avgt 30 12.204 ± 0.186 ns/op
, где ллойдмета состояния
Так что в настоящее время ситуация такова, что Java EnumMap и EnumSet примерно в 2 раза быстрее, чем обычные Scala Set и Maps с Enumeratum, но, учитывая, что мы все еще в диапазоне менее 10 нс, кажется разумным сказать, что производительность здесь не будет узкого места, за исключением случаев с супер-гранями.
Я попытался повторить тесты Ллойдметы и получил следующие результаты с Scala 2.13, перечисление 1.5.15
sbt "jmh:run -i 10 -wi 10 -f 2 -t 1 -prof gc bench.So60374058"
Среднее время, время / операция
enumeratumScalaMapGet avgt 20 8.284 ± 0.071 ns/op
jEnumEnumMapGet avgt 20 2.883 ± 0.023 ns/op
jEnumScalaMapGet avgt 20 7.361 ± 0.273 ns/op
vanillaScalaMapGet avgt 20 6.650 ± 0.323 ns/op
Скорость выделения памяти
enumeratumScalaMapGet:·gc.alloc.rate avgt 20 1753.262 ± 14.548 MB/sec
jEnumEnumMapGet:·gc.alloc.rate avgt 20 ≈ 10⁻⁴ MB/sec
jEnumScalaMapGet:·gc.alloc.rate avgt 20 1976.491 ± 70.259 MB/sec
vanillaScalaMapGet:·gc.alloc.rate avgt 20 2190.644 ± 105.208 MB/sec
Мы отмечаем, jEnumScalaMapGet
, кажется, поймали с enumeratumScalaMapGet
с 2017 года и тривиальным выделением памяти jEnumEnumMapGet
.
Исходный источник:
public enum JAgeGroup {
Baby,
Toddler,
Teenager,
Adult,
Senior
}
и
import java.util
import java.util.concurrent.TimeUnit
import example.JAgeGroup
import org.openjdk.jmh.annotations._
import org.openjdk.jmh.infra.Blackhole
import enumeratum._
object AgeGroupVanilla extends Enumeration {
type AgeGroupVanilla = Value
val Baby, Toddler, Teenager, Adult, Senior = Value
}
sealed trait AgeGroup extends EnumEntry
case object AgeGroup extends Enum[AgeGroup] {
val values = findValues
case object Baby extends AgeGroup
case object Toddler extends AgeGroup
case object Teenager extends AgeGroup
case object Adult extends AgeGroup
case object Senior extends AgeGroup
}
@State(Scope.Thread)
@BenchmarkMode(Array(Mode.AverageTime))
@OutputTimeUnit(TimeUnit.NANOSECONDS)
class So60374058 {
private val jEnumEnumMap = {
val m: util.EnumMap[JAgeGroup, String] = new util.EnumMap(classOf[JAgeGroup])
JAgeGroup.values().foreach(e => m.put(e, e.name()))
m
}
private val jEnumScalaMap = Map(JAgeGroup.values().map(e => e -> e.name()): _*)
private val ageGroupScalaMap = Map(AgeGroup.values.map(e => e -> e.entryName): _*)
private val vanillaScalaMap = AgeGroupVanilla.values.map(e => e -> e.toString).toMap
private def randomFrom[A](seq: Seq[A]): A = {
seq(scala.util.Random.nextInt(seq.size))
}
private var jEnum: JAgeGroup = _
private var ageGroupEnum: AgeGroup = _
private var vanillaEnum: AgeGroupVanilla.AgeGroupVanilla = _
@Setup(Level.Trial)
def setup(): Unit = {
jEnum = randomFrom(JAgeGroup.values())
ageGroupEnum = randomFrom(AgeGroup.values)
vanillaEnum = randomFrom(AgeGroupVanilla.values.toSeq)
}
@Benchmark
def jEnumEnumMapGet(bh: Blackhole): Unit = bh.consume {
jEnumEnumMap.get(jEnum)
}
@Benchmark
def jEnumScalaMapGet(bh: Blackhole): Unit = bh.consume {
jEnumScalaMap.get(jEnum)
}
@Benchmark
def enumeratumScalaMapGet(bh: Blackhole): Unit = bh.consume {
ageGroupScalaMap.get(ageGroupEnum)
}
@Benchmark
def vanillaScalaMapGet(bh: Blackhole): Unit = bh.consume {
vanillaScalaMap.get(vanillaEnum)
}
}