Simplify K/N ArrayList
This commit specializes the existing Kotlin/Native stdlib ArrayList into two subclasses: * ArrayList * ArraySubList This avoids repeatedly checking whether a basic ArrayList is created as a sublist of another ArrayList. In the iterators, checkForComodification is marked for inlining, since this significantly improves iterations performance. A number of benchmarks are added to the native ring benchmark suite, to test whether the changed runtime type of ArrayList.subList(...) has an impact.
This commit is contained in:
committed by
Space Cloud
parent
39fda3535a
commit
d62dbbb1bd
@@ -218,6 +218,15 @@ class RingLauncher : Launcher() {
|
||||
"ParameterNotNull.invokeEightArgsWithNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeEightArgsWithNullCheck() }),
|
||||
"ParameterNotNull.invokeEightArgsWithoutNullCheck" to BenchmarkEntryWithInit.create(::ParameterNotNullAssertionBenchmark, { invokeEightArgsWithoutNullCheck() }),
|
||||
"String.stringConcatNullable" to BenchmarkEntryWithInit.create(::StringBenchmark, { stringConcatNullable() }),
|
||||
"SubList.concatenate" to BenchmarkEntryWithInit.create(::SubListBenchmark, { concatenate() }),
|
||||
"SubList.concatenateManual" to BenchmarkEntryWithInit.create(::SubListBenchmark, { concatenateManual() }),
|
||||
"SubList.filterAndCount" to BenchmarkEntryWithInit.create(::SubListBenchmark, { filterAndCount() }),
|
||||
"SubList.filterAndCountWithLambda" to BenchmarkEntryWithInit.create(::SubListBenchmark, { filterAndCountWithLambda() }),
|
||||
"SubList.countWithLambda" to BenchmarkEntryWithInit.create(::SubListBenchmark, { countWithLambda() }),
|
||||
"SubList.filterManual" to BenchmarkEntryWithInit.create(::SubListBenchmark, { filterManual() }),
|
||||
"SubList.countFilteredManual" to BenchmarkEntryWithInit.create(::SubListBenchmark, { countFilteredManual() }),
|
||||
"SubList.countFiltered" to BenchmarkEntryWithInit.create(::SubListBenchmark, { countFiltered() }),
|
||||
"SubList.reduce" to BenchmarkEntryWithInit.create(::SubListBenchmark, { reduce() }),
|
||||
"Switch.testSparseIntSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testSparseIntSwitch() }),
|
||||
"Switch.testDenseIntSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testDenseIntSwitch() }),
|
||||
"Switch.testConstSwitch" to BenchmarkEntryWithInit.create(::SwitchBenchmark, { testConstSwitch() }),
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.ring
|
||||
|
||||
class SubListBenchmark {
|
||||
private var _data: List<Value>? = null
|
||||
|
||||
fun getData(subList: Boolean): List<Value> {
|
||||
val data: List<Value> = _data!!
|
||||
// 1 to ensure that .subList can't return the list itself
|
||||
if (subList) return data.subList(1, data.size)
|
||||
else return data
|
||||
}
|
||||
|
||||
init {
|
||||
val list = ArrayList<Value>(BENCHMARK_SIZE)
|
||||
for (n in classValues(BENCHMARK_SIZE))
|
||||
list.add(n)
|
||||
_data = list
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun concatenate(): List<Value> {
|
||||
return getData(false) + getData(true)
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun concatenateManual(): List<Value> {
|
||||
val list = ArrayList<Value>(2 * BENCHMARK_SIZE)
|
||||
// outer loop to ensure single call site for list and sublist
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
for (item in data) {
|
||||
list.add(item)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun filterAndCount(): Int {
|
||||
var count = 0
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
count += data.filter { filterLoad(it) }.count()
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun filterAndCountWithLambda(): Int {
|
||||
var count = 0
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
count += data.filter { it.value % 2 == 0 }.count()
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun countWithLambda(): Int {
|
||||
var count = 0
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
count += data.count { it.value % 2 == 0 }
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun filterManual(): List<Value> {
|
||||
val list = ArrayList<Value>()
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
for (it in data) {
|
||||
if (filterLoad(it))
|
||||
list.add(it)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun countFilteredManual(): Int {
|
||||
var count = 0
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
for (it in data) {
|
||||
if (filterLoad(it))
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun countFiltered(): Int {
|
||||
var count = 0
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
count += data.count { filterLoad(it) }
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
//Benchmark
|
||||
fun reduce(): Int {
|
||||
var res = 0
|
||||
for (data in listOf(getData(false), getData(true))) {
|
||||
res = data.fold(res) { acc, it -> if (filterLoad(it)) acc + 1 else acc }
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user