Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.

Commit 54f4927

Browse files
authored
Merge pull request #7 from k163377/improve_performance
Improve performance.
2 parents d84ff04 + 12357a2 commit 54f4927

File tree

6 files changed

+97
-17
lines changed

6 files changed

+97
-17
lines changed

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,6 @@ jmh {
6262
threads = 3
6363
warmupBatchSize = 3
6464
warmupIterations = 3
65+
66+
resultFormat = "CSV"
6567
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.mapk.fastkfunction.spreadwrapper;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.lang.reflect.Constructor;
6+
import java.lang.reflect.InvocationTargetException;
7+
8+
public class ForConstructor<T> implements SpreadWrapper<T> {
9+
private final Constructor<T> constructor;
10+
11+
public ForConstructor(@NotNull Constructor<T> constructor) {
12+
this.constructor = constructor;
13+
}
14+
15+
@Override
16+
public T call(Object[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
17+
return constructor.newInstance(args);
18+
}
19+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.mapk.fastkfunction.spreadwrapper;
2+
3+
import kotlin.reflect.KFunction;
4+
import org.jetbrains.annotations.NotNull;
5+
6+
public class ForKFunction<T> implements SpreadWrapper<T> {
7+
private final KFunction<T> kFunction;
8+
9+
public ForKFunction(@NotNull KFunction<T> kFunction) {
10+
this.kFunction = kFunction;
11+
}
12+
13+
@Override
14+
public T call(Object[] args) {
15+
return kFunction.call(args);
16+
}
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.mapk.fastkfunction.spreadwrapper;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.Nullable;
5+
6+
import java.lang.reflect.InvocationTargetException;
7+
import java.lang.reflect.Method;
8+
9+
public class ForMethod implements SpreadWrapper<Object> {
10+
private final Method method;
11+
private final Object instance;
12+
13+
public ForMethod(@NotNull Method method, @Nullable Object instance) {
14+
this.method = method;
15+
this.instance = instance;
16+
}
17+
18+
@Override
19+
public Object call(Object[] args) throws InvocationTargetException, IllegalAccessException {
20+
return method.invoke(instance, args);
21+
}
22+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.mapk.fastkfunction.spreadwrapper;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
5+
/**
6+
* Wrapper to avoid using Kotlin's heavy spread operator.
7+
* @param <T> return type
8+
*/
9+
public interface SpreadWrapper<T> {
10+
T call(Object[] args) throws InvocationTargetException, IllegalAccessException, InstantiationException;
11+
}

src/main/kotlin/com/mapk/fastkfunction/FastKFunction.kt

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package com.mapk.fastkfunction
22

33
import com.mapk.fastkfunction.argumentbucket.ArgumentBucket
44
import com.mapk.fastkfunction.argumentbucket.BucketGenerator
5+
import com.mapk.fastkfunction.spreadwrapper.ForConstructor
6+
import com.mapk.fastkfunction.spreadwrapper.ForKFunction
7+
import com.mapk.fastkfunction.spreadwrapper.ForMethod
58
import java.lang.reflect.Method
69
import java.lang.reflect.Modifier
710
import kotlin.reflect.KFunction
@@ -22,64 +25,68 @@ sealed class FastKFunction<T> {
2225

2326
internal class Constructor<T>(
2427
private val function: KFunction<T>,
25-
private val constructor: JavaConstructor<T>,
28+
constructor: JavaConstructor<T>,
2629
override val valueParameters: List<KParameter>
2730
) : FastKFunction<T>() {
31+
private val spreadWrapper = ForConstructor(constructor)
2832
override val bucketGenerator = BucketGenerator(valueParameters, null)
2933

3034
override fun callBy(bucket: ArgumentBucket): T = if (bucket.isFullInitialized()) {
31-
constructor.newInstance(*bucket.getValueArray())
35+
spreadWrapper.call(bucket.getValueArray())
3236
} else {
3337
function.callBy(bucket)
3438
}
3539

36-
override fun callByCollection(args: Collection<Any?>): T = constructor.newInstance(*args.toTypedArray())
40+
override fun callByCollection(args: Collection<Any?>): T = spreadWrapper.call(args.toTypedArray())
3741

38-
override fun call(vararg args: Any?): T = constructor.newInstance(*args)
42+
override fun call(vararg args: Any?): T = spreadWrapper.call(args)
3943
}
4044

4145
internal class Function<T>(
4246
private val function: KFunction<T>,
4347
override val valueParameters: List<KParameter>
4448
) : FastKFunction<T>() {
49+
private val spreadWrapper = ForKFunction(function)
4550
override val bucketGenerator = BucketGenerator(valueParameters, null)
4651

4752
override fun callBy(bucket: ArgumentBucket): T = if (bucket.isFullInitialized()) {
48-
function.call(*bucket.getValueArray())
53+
spreadWrapper.call(bucket.getValueArray())
4954
} else {
5055
function.callBy(bucket)
5156
}
5257

53-
override fun callByCollection(args: Collection<Any?>): T = function.call(*args.toTypedArray())
58+
override fun callByCollection(args: Collection<Any?>): T = spreadWrapper.call(args.toTypedArray())
5459

55-
override fun call(vararg args: Any?): T = function.call(*args)
60+
override fun call(vararg args: Any?): T = spreadWrapper.call(args)
5661
}
5762

5863
internal class TopLevelFunction<T>(
5964
private val function: KFunction<T>,
60-
private val method: Method,
65+
method: Method,
6166
override val valueParameters: List<KParameter>
6267
) : FastKFunction<T>() {
68+
private val spreadWrapper = ForMethod(method, null)
6369
override val bucketGenerator = BucketGenerator(valueParameters, null)
6470

6571
@Suppress("UNCHECKED_CAST")
6672
override fun callBy(bucket: ArgumentBucket): T = if (bucket.isFullInitialized()) {
67-
method.invoke(null, *bucket.getValueArray()) as T
73+
spreadWrapper.call(bucket.getValueArray()) as T
6874
} else {
6975
function.callBy(bucket)
7076
}
7177

7278
@Suppress("UNCHECKED_CAST")
73-
override fun callByCollection(args: Collection<Any?>): T = method.invoke(null, *args.toTypedArray()) as T
79+
override fun callByCollection(args: Collection<Any?>): T = spreadWrapper.call(args.toTypedArray()) as T
7480

7581
@Suppress("UNCHECKED_CAST")
76-
override fun call(vararg args: Any?): T = method.invoke(null, *args) as T
82+
override fun call(vararg args: Any?): T = spreadWrapper.call(args) as T
7783
}
7884

85+
// NOTE: トップレベル拡張関数に関してはスプレッド演算子抹消対応が難しい(Bucket関連を弄らなきゃ無理)ため、一旦手を付けていない
7986
internal class TopLevelExtensionFunction<T>(
8087
private val function: KFunction<T>,
8188
private val method: Method,
82-
private val extensionReceiver: Any?,
89+
private val extensionReceiver: Any,
8390
override val bucketGenerator: BucketGenerator,
8491
override val valueParameters: List<KParameter>
8592
) : FastKFunction<T>() {
@@ -100,23 +107,25 @@ sealed class FastKFunction<T> {
100107

101108
internal class InstanceFunction<T>(
102109
private val function: KFunction<T>,
103-
private val method: Method,
104-
private val instance: Any,
110+
method: Method,
111+
instance: Any,
105112
override val bucketGenerator: BucketGenerator,
106113
override val valueParameters: List<KParameter>
107114
) : FastKFunction<T>() {
115+
private val spreadWrapper = ForMethod(method, instance)
116+
108117
@Suppress("UNCHECKED_CAST")
109118
override fun callBy(bucket: ArgumentBucket): T = if (bucket.isFullInitialized()) {
110-
method.invoke(instance, *bucket.getValueArray()) as T
119+
spreadWrapper.call(bucket.getValueArray()) as T
111120
} else {
112121
function.callBy(bucket)
113122
}
114123

115124
@Suppress("UNCHECKED_CAST")
116-
override fun callByCollection(args: Collection<Any?>): T = method.invoke(instance, *args.toTypedArray()) as T
125+
override fun callByCollection(args: Collection<Any?>): T = spreadWrapper.call(args.toTypedArray()) as T
117126

118127
@Suppress("UNCHECKED_CAST")
119-
override fun call(vararg args: Any?): T = method.invoke(instance, *args) as T
128+
override fun call(vararg args: Any?): T = spreadWrapper.call(args) as T
120129
}
121130

122131
companion object {

0 commit comments

Comments
 (0)