From 409d1024765bfe3c4fb8b49b7ebd4422ad23a79d Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 12:39:20 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=E3=82=B2=E3=83=83=E3=82=BF=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5=E3=82=92?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/KMapper.kt | 31 +++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/KMapper.kt b/src/main/kotlin/com/mapk/kmapper/KMapper.kt index dc9461e..bb14b33 100644 --- a/src/main/kotlin/com/mapk/kmapper/KMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/KMapper.kt @@ -31,7 +31,23 @@ class KMapper private constructor( .filter { it.kind != KParameter.Kind.INSTANCE && !it.isUseDefaultArgument() } .associate { (parameterNameConverter(it.getAliasOrName()!!)) to ParameterForMap.newInstance(it) } + private val getCache: MutableMap, List<(Any, ArgumentBucket) -> Unit>> = HashMap() + private fun bindArguments(argumentBucket: ArgumentBucket, src: Any) { + val clazz = src::class + + // キャッシュヒットしたら登録した内容に沿って取得処理を行う + getCache[clazz]?.let { getters -> + getters.forEach { + it(src, argumentBucket) + // 終了判定 + if (argumentBucket.isInitialized) return + } + return + } + + val tempCacheArrayList = ArrayList<(Any, ArgumentBucket) -> Unit>() + src::class.memberProperties.forEach outer@{ property -> // propertyが公開されていない場合は処理を行わない if (property.visibility != KVisibility.PUBLIC) return@outer @@ -46,14 +62,19 @@ class KMapper private constructor( if (it is KGetterAlias) alias = it.value } - parameterMap[alias ?: property.name]?.let { - // javaGetterを呼び出す方が高速 + parameterMap[alias ?: property.name]?.let { param -> javaGetter.isAccessible = true - argumentBucket.putIfAbsent(it.param, javaGetter.invoke(src)?.let { value -> it.mapObject(value) }) - // 終了判定 - if (argumentBucket.isInitialized) return + + val tempCache = { value: Any, bucket: ArgumentBucket -> + // javaGetterを呼び出す方が高速 + bucket.putIfAbsent(param.param, javaGetter.invoke(value)?.let { param.mapObject(it) }) + } + tempCache(src, argumentBucket) + tempCacheArrayList.add(tempCache) + // キャッシュの整合性を保つため、ここでは終了判定を行わない } } + getCache[clazz] = tempCacheArrayList } private fun bindArguments(argumentBucket: ArgumentBucket, src: Map<*, *>) { From 18c39c6c1ee1ca2ae5377d181a8ff20aa8683f0d Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 13:02:01 +0900 Subject: [PATCH 2/8] =?UTF-8?q?ConcurrentMap=E3=81=AB=E3=81=97=E3=81=A6?= =?UTF-8?q?=E4=B8=A6=E5=88=97=E5=AE=9F=E8=A1=8C=E3=81=95=E3=82=8C=E3=81=9F?= =?UTF-8?q?=E6=99=82=E3=81=AB=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=81=8C=E5=A3=8A=E3=82=8C=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/KMapper.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/KMapper.kt b/src/main/kotlin/com/mapk/kmapper/KMapper.kt index bb14b33..3f1bb70 100644 --- a/src/main/kotlin/com/mapk/kmapper/KMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/KMapper.kt @@ -8,6 +8,8 @@ import com.mapk.core.getAliasOrName import com.mapk.core.isUseDefaultArgument import com.mapk.core.toKConstructor import java.lang.reflect.Method +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap import kotlin.reflect.KClass import kotlin.reflect.KFunction import kotlin.reflect.KParameter @@ -31,7 +33,7 @@ class KMapper private constructor( .filter { it.kind != KParameter.Kind.INSTANCE && !it.isUseDefaultArgument() } .associate { (parameterNameConverter(it.getAliasOrName()!!)) to ParameterForMap.newInstance(it) } - private val getCache: MutableMap, List<(Any, ArgumentBucket) -> Unit>> = HashMap() + private val getCache: ConcurrentMap, List<(Any, ArgumentBucket) -> Unit>> = ConcurrentHashMap() private fun bindArguments(argumentBucket: ArgumentBucket, src: Any) { val clazz = src::class @@ -74,7 +76,7 @@ class KMapper private constructor( // キャッシュの整合性を保つため、ここでは終了判定を行わない } } - getCache[clazz] = tempCacheArrayList + getCache.putIfAbsent(clazz, tempCacheArrayList) } private fun bindArguments(argumentBucket: ArgumentBucket, src: Map<*, *>) { From 09d6cbb5ba6bc80ef11696873aeaa04ee378fb2d Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 13:02:04 +0900 Subject: [PATCH 3/8] =?UTF-8?q?ConcurrentMap=E3=81=AB=E3=81=97=E3=81=A6?= =?UTF-8?q?=E4=B8=A6=E5=88=97=E5=AE=9F=E8=A1=8C=E3=81=95=E3=82=8C=E3=81=9F?= =?UTF-8?q?=E6=99=82=E3=81=AB=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=81=8C=E5=A3=8A=E3=82=8C=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt index 4dd300e..cb4fa9e 100644 --- a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt @@ -1,6 +1,8 @@ package com.mapk.kmapper import com.mapk.core.EnumMapper +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap import kotlin.reflect.KClass import kotlin.reflect.KFunction import kotlin.reflect.KParameter @@ -13,7 +15,7 @@ internal class ParameterForMap private constructor(val param: KParamete // リストの長さが小さいと期待されるためこの形で実装しているが、理想的にはmap的なものが使いたい private val converters: Set, KFunction>> = clazz.getConverters() - private val convertCache: MutableMap, (Any) -> Any?> = HashMap() + private val convertCache: ConcurrentMap, (Any) -> Any?> = ConcurrentHashMap() fun mapObject(value: U): Any? { val valueClazz: KClass<*> = value::class @@ -38,7 +40,7 @@ internal class ParameterForMap private constructor(val param: KParamete clazz == String::class -> { { it.toString() } } else -> throw IllegalArgumentException("Can not convert $valueClazz to $clazz") } - convertCache[valueClazz] = lambda + convertCache.putIfAbsent(valueClazz, lambda) return lambda(value) } From bcdc83952e548cecabb465f9962832695dbbbdd9 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 13:02:17 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=A2=E3=83=83=E3=83=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 2ec2853..6073570 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "com.mapk" -version = "0.21" +version = "0.22" java { sourceCompatibility = JavaVersion.VERSION_1_8 From 40e627dfbfac01255c34fa365d9ebb06e0840034 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 13:29:10 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=E5=8F=96=E5=BE=97=E5=AF=BE=E8=B1=A1?= =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=89=E3=81=AF=E5=8D=81?= =?UTF-8?q?=E5=88=86=E7=B5=9E=E3=82=8A=E8=BE=BC=E3=82=93=E3=81=A7=E3=81=84?= =?UTF-8?q?=E3=82=8B=E3=81=A8=E8=80=83=E3=81=88=E3=82=89=E3=82=8C=E3=82=8B?= =?UTF-8?q?=E3=81=9F=E3=82=81=E3=80=81=E7=B5=82=E4=BA=86=E5=88=A4=E5=AE=9A?= =?UTF-8?q?=E3=81=AF=E8=A1=8C=E3=82=8F=E3=81=AA=E3=81=84=E3=82=88=E3=81=86?= =?UTF-8?q?=E6=9C=80=E9=81=A9=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/KMapper.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/KMapper.kt b/src/main/kotlin/com/mapk/kmapper/KMapper.kt index 3f1bb70..3f9500c 100644 --- a/src/main/kotlin/com/mapk/kmapper/KMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/KMapper.kt @@ -40,11 +40,8 @@ class KMapper private constructor( // キャッシュヒットしたら登録した内容に沿って取得処理を行う getCache[clazz]?.let { getters -> - getters.forEach { - it(src, argumentBucket) - // 終了判定 - if (argumentBucket.isInitialized) return - } + // 取得対象フィールドは十分絞り込んでいると考えられるため、終了判定は行わない + getters.forEach { it(src, argumentBucket) } return } From 5f313dd3cf77160186a373ffc7e143ec26b08e04 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 13:42:31 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=E5=88=9D=E6=9C=9F=E5=8C=96=E6=B8=88?= =?UTF-8?q?=E3=81=BF=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=89=E3=82=92?= =?UTF-8?q?=E7=84=A1=E8=A6=96=E3=81=99=E3=82=8B=E5=87=A6=E7=90=86=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/KMapper.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/KMapper.kt b/src/main/kotlin/com/mapk/kmapper/KMapper.kt index 3f9500c..910cead 100644 --- a/src/main/kotlin/com/mapk/kmapper/KMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/KMapper.kt @@ -65,8 +65,11 @@ class KMapper private constructor( javaGetter.isAccessible = true val tempCache = { value: Any, bucket: ArgumentBucket -> - // javaGetterを呼び出す方が高速 - bucket.putIfAbsent(param.param, javaGetter.invoke(value)?.let { param.mapObject(it) }) + // 初期化済みであれば高コストな取得処理は行わない + if (!bucket.containsKey(param.param)) { + // javaGetterを呼び出す方が高速 + bucket.putIfAbsent(param.param, javaGetter.invoke(value)?.let { param.mapObject(it) }) + } } tempCache(src, argumentBucket) tempCacheArrayList.add(tempCache) From 72692c48a913de866ec48eaaefa960f9a8591a05 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 13:42:54 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=E6=9C=80=E5=88=9D=E3=81=AB=E3=83=9E?= =?UTF-8?q?=E3=83=83=E3=83=97=E3=81=97=E3=81=9F=E5=80=A4=E3=82=92=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E3=81=97=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E3=83=90?= =?UTF-8?q?=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt index cb4fa9e..9f599c3 100644 --- a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt @@ -25,7 +25,7 @@ internal class ParameterForMap private constructor(val param: KParamete // パラメータに対してvalueが代入可能(同じもしくは親クラス)であればそのまま用いる if (clazz.isSuperclassOf(valueClazz)) { - convertCache[valueClazz] = { value } + convertCache[valueClazz] = { it } return value } From aa9ca10add394fe0fd43e8e41fbfb24b81991798 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 12 Apr 2020 14:09:51 +0900 Subject: [PATCH 8/8] =?UTF-8?q?putIfAbsent=E3=81=A7=E3=81=8D=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt index 9f599c3..25d1875 100644 --- a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt @@ -25,7 +25,7 @@ internal class ParameterForMap private constructor(val param: KParamete // パラメータに対してvalueが代入可能(同じもしくは親クラス)であればそのまま用いる if (clazz.isSuperclassOf(valueClazz)) { - convertCache[valueClazz] = { it } + convertCache.putIfAbsent(valueClazz) { it } return value }