Skip to content

Commit 18b7c32

Browse files
author
Abduqodiri Qurbonzoda
committed
Kotlin immutable collections benchmarks
1 parent 92d2e54 commit 18b7c32

40 files changed

+1830
-2
lines changed

benchmarks-mpp/build.gradle

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
plugins {
2+
id 'org.jetbrains.kotlin.multiplatform' version '1.3.31'
3+
id 'org.jetbrains.gradle.benchmarks.plugin' version '0.1.7-dev-21'
4+
}
5+
6+
repositories {
7+
mavenCentral()
8+
maven { url 'https://dl.bintray.com/orangy/maven' }
9+
}
10+
11+
apply plugin: 'maven-publish'
12+
13+
kotlin {
14+
jvm()
15+
16+
sourceSets {
17+
commonMain {
18+
}
19+
commonTest {
20+
}
21+
jvmMain {
22+
dependencies {
23+
implementation kotlin('stdlib-jdk8')
24+
implementation project(path: ':kotlinx-collections-immutable')
25+
implementation 'org.jetbrains.gradle.benchmarks:runtime-jvm:0.1.7-dev-21'
26+
}
27+
}
28+
jvmTest {
29+
}
30+
}
31+
}
32+
33+
benchmark {
34+
configurations {
35+
register("jvm") {
36+
jmhVersion = "1.21"
37+
}
38+
}
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks
18+
19+
class ObjectWrapper<K: Comparable<K>>(val obj: K, val hashCode: Int) : Comparable<ObjectWrapper<K>> {
20+
override fun hashCode(): Int {
21+
return hashCode
22+
}
23+
24+
override fun equals(other: Any?): Boolean {
25+
if (other !is ObjectWrapper<*>) {
26+
return false
27+
}
28+
assert(obj != other.obj || hashCode == other.hashCode) // if elements are equal hashCodes must be equal
29+
return obj == other.obj
30+
}
31+
32+
override fun compareTo(other: ObjectWrapper<K>): Int {
33+
return obj.compareTo(other.obj)
34+
}
35+
}
36+
37+
38+
typealias IntWrapper = ObjectWrapper<Int>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks
18+
19+
const val BM_1 = "1"
20+
const val BM_10 = "10"
21+
const val BM_100 = "100"
22+
const val BM_1000 = "1000"
23+
const val BM_10000 = "10000"
24+
const val BM_100000 = "100000"
25+
const val BM_1000000 = "1000000"
26+
const val BM_10000000 = "10000000"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks
18+
19+
import java.util.*
20+
21+
const val ASCENDING_HASH_CODE = "ascending"
22+
const val RANDOM_HASH_CODE = "random"
23+
const val COLLISION_HASH_CODE = "collision"
24+
const val NON_EXISTING_HASH_CODE = "nonExisting"
25+
26+
private inline fun intWrappers(size: Int, hashCodeGenerator: (index: Int) -> Int): List<IntWrapper> {
27+
val keys = mutableListOf<IntWrapper>()
28+
repeat(size) {
29+
keys.add(IntWrapper(it, hashCodeGenerator(it)))
30+
}
31+
return keys
32+
}
33+
34+
private fun generateIntWrappers(hashCodeType: String, size: Int): List<IntWrapper> {
35+
val random = Random(40)
36+
return when(hashCodeType) {
37+
ASCENDING_HASH_CODE -> intWrappers(size) { it }
38+
RANDOM_HASH_CODE,
39+
NON_EXISTING_HASH_CODE -> intWrappers(size) { random.nextInt() }
40+
COLLISION_HASH_CODE -> intWrappers(size) { random.nextInt((size + 1) / 2) }
41+
else -> throw AssertionError("Unknown hashCodeType: $hashCodeType")
42+
}
43+
}
44+
45+
fun generateKeys(hashCodeType: String, size: Int) = generateIntWrappers(hashCodeType, size)
46+
fun generateElements(hashCodeType: String, size: Int) = generateIntWrappers(hashCodeType, size)
47+
48+
49+
const val HASH_IMPL = "hash"
50+
const val ORDERED_IMPL = "ordered"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks.immutableList
18+
19+
import benchmarks.*
20+
import kotlinx.collections.immutable.ImmutableList
21+
import org.openjdk.jmh.annotations.*
22+
import org.openjdk.jmh.infra.Blackhole
23+
24+
@State(Scope.Thread)
25+
open class Add {
26+
@Param(BM_1, BM_10, BM_100, BM_1000, BM_10000, BM_100000, BM_1000000, BM_10000000)
27+
var size: Int = 0
28+
29+
@Benchmark
30+
fun addLast(): ImmutableList<String> {
31+
return persistentListAdd(size)
32+
}
33+
34+
@Benchmark
35+
fun addLastAndIterate(bh: Blackhole) {
36+
val list = persistentListAdd(size)
37+
for (e in list) {
38+
bh.consume(e)
39+
}
40+
}
41+
42+
@Benchmark
43+
fun addLastAndGet(bh: Blackhole) {
44+
val list = persistentListAdd(size)
45+
for (i in 0 until list.size) {
46+
bh.consume(list[i])
47+
}
48+
}
49+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks.immutableList
18+
19+
import benchmarks.*
20+
import kotlinx.collections.immutable.PersistentList
21+
import kotlinx.collections.immutable.persistentListOf
22+
import org.openjdk.jmh.annotations.*
23+
import org.openjdk.jmh.infra.Blackhole
24+
25+
@State(Scope.Benchmark)
26+
open class Get {
27+
@Param(BM_1, BM_10, BM_100, BM_1000, BM_10000, BM_100000, BM_1000000, BM_10000000)
28+
var size: Int = 0
29+
30+
private var persistentList: PersistentList<String> = persistentListOf()
31+
32+
@Setup(Level.Trial)
33+
fun prepare() {
34+
persistentList = persistentListAdd(size)
35+
}
36+
37+
@Benchmark
38+
fun getByIndex(bh: Blackhole) {
39+
for (i in 0 until persistentList.size) {
40+
bh.consume(persistentList[i])
41+
}
42+
}
43+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks.immutableList
18+
19+
import benchmarks.*
20+
import kotlinx.collections.immutable.PersistentList
21+
import kotlinx.collections.immutable.persistentListOf
22+
import org.openjdk.jmh.annotations.*
23+
import org.openjdk.jmh.infra.Blackhole
24+
25+
@State(Scope.Benchmark)
26+
open class Iterate {
27+
@Param(BM_1, BM_10, BM_100, BM_1000, BM_10000, BM_100000, BM_1000000, BM_10000000)
28+
var size: Int = 0
29+
30+
private var persistentList: PersistentList<String> = persistentListOf()
31+
32+
@Setup(Level.Trial)
33+
fun prepare() {
34+
persistentList = persistentListAdd(size)
35+
}
36+
37+
@Benchmark
38+
fun firstToLast(bh: Blackhole) {
39+
for (e in persistentList) {
40+
bh.consume(e)
41+
}
42+
}
43+
44+
@Benchmark
45+
fun lastToFirst(bh: Blackhole) {
46+
val iterator = persistentList.listIterator(size)
47+
48+
while (iterator.hasPrevious()) {
49+
bh.consume(iterator.previous())
50+
}
51+
}
52+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package benchmarks.immutableList
18+
19+
import benchmarks.*
20+
import kotlinx.collections.immutable.ImmutableList
21+
import kotlinx.collections.immutable.PersistentList
22+
import kotlinx.collections.immutable.persistentListOf
23+
import org.openjdk.jmh.annotations.*
24+
25+
@State(Scope.Thread)
26+
open class Remove {
27+
@Param(BM_1, BM_10, BM_100, BM_1000, BM_10000, BM_100000, BM_1000000, BM_10000000)
28+
var size: Int = 0
29+
30+
private var persistentList: PersistentList<String> = persistentListOf()
31+
32+
@Setup(Level.Trial)
33+
fun prepare() {
34+
persistentList = persistentListAdd(size)
35+
}
36+
37+
@Benchmark
38+
fun removeLast(): ImmutableList<String> {
39+
var list = persistentList
40+
repeat(times = size) {
41+
list = list.removeAt(list.size - 1)
42+
}
43+
return list
44+
}
45+
}

0 commit comments

Comments
 (0)