Optimize memory usage during import of MPP projects

#KT-30767 Fixed
This commit is contained in:
Andrey Uskov
2019-04-02 10:40:46 +03:00
parent 3ca1c7b55d
commit 792fae4afc
4 changed files with 61 additions and 20 deletions
@@ -196,7 +196,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
if (LOG.isDebugEnabled) {
LOG.debug("Start populate module dependencies. Gradle module: [$gradleModule], Ide module: [$ideModule], Ide project: [$ideProject]")
}
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) }
val mppModel = resolverCtx.getMppModel(gradleModule)
if (mppModel != null) {
mppModel.targets.forEach { target ->
KotlinStatisticsTrigger.trigger(
@@ -45,6 +45,7 @@ import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil.ge
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File
import java.util.*
@Order(ExternalSystemConstants.UNORDERED + 1)
open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
@@ -83,7 +84,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
super.populateModuleCompileOutputSettings(gradleModule, ideModule)
}
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) } ?: return
val mppModel = resolverCtx.getMppModel(gradleModule) ?: return
val ideaOutDir = File(ideModule.data.linkedExternalProjectPath, "out")
val projectDataNode = ideModule.getDataNode(ProjectKeys.PROJECT)!!
val moduleOutputsMap = projectDataNode.getUserData(MODULES_OUTPUTS)!!
@@ -153,6 +154,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
}
companion object {
val proxyObjectCloningCache = WeakHashMap<Any, Any>()
fun initializeModuleData(
gradleModule: IdeaModule,
mainModuleNode: DataNode<ModuleData>,
@@ -164,7 +167,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
val mainModuleFileDirectoryPath = mainModuleData.moduleFileDirectoryPath
val externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject::class.java)
val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) }
val mppModel = resolverCtx.getMppModel(gradleModule)
if (mppModel == null || externalProject == null) return
val jdkName = gradleModule.jdkNameIfAny
@@ -311,8 +314,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
ideModule: DataNode<ModuleData>,
resolverCtx: ProjectResolverContext
) {
val mppModel =
resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) } ?: return
val mppModel = resolverCtx.getMppModel(gradleModule) ?: return
if (resolverCtx.getExtraProject(gradleModule, ExternalProject::class.java) == null) return
processSourceSets(gradleModule, mppModel, ideModule, resolverCtx) { dataNode, sourceSet ->
if (dataNode == null || sourceSet.platform == KotlinPlatform.ANDROID) return@processSourceSets
@@ -339,8 +341,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
ideModule: DataNode<ModuleData>,
resolverCtx: ProjectResolverContext
) {
val mppModel =
resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)?.let { KotlinMPPGradleModelImpl(it) } ?: return
val mppModel = resolverCtx.getMppModel(gradleModule) ?: return
val sourceSetMap = ideProject.getUserData(GradleProjectResolver.RESOLVED_SOURCE_SETS) ?: return
val artifactsMap = ideProject.getUserData(CONFIGURATION_ARTIFACTS) ?: return
val substitutor = KotlinNativeLibrariesDependencySubstitutor(mppModel, gradleModule, resolverCtx)
@@ -615,7 +616,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
resolverCtx: ProjectResolverContext
): KotlinSourceSetInfo? {
if (sourceSet.platform.isNotSupported()) return null
return KotlinSourceSetInfo(KotlinSourceSetImpl(sourceSet)).also { info ->
return KotlinSourceSetInfo(sourceSet).also { info ->
val languageSettings = sourceSet.languageSettings
info.moduleId = getKotlinModuleId(gradleModule, sourceSet, resolverCtx)
info.gradleModuleId = getModuleId(resolverCtx, gradleModule)
@@ -645,7 +646,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
resolverCtx: ProjectResolverContext
): KotlinSourceSetInfo? {
if (compilation.platform.isNotSupported()) return null
return KotlinSourceSetInfo(KotlinCompilationImpl(compilation)).also { sourceSetInfo ->
return KotlinSourceSetInfo(compilation).also { sourceSetInfo ->
sourceSetInfo.moduleId = getKotlinModuleId(gradleModule, compilation, resolverCtx)
sourceSetInfo.gradleModuleId = getModuleId(resolverCtx, gradleModule)
sourceSetInfo.platform = compilation.platform
@@ -697,3 +698,15 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() {
) ?: false
}
}
fun ProjectResolverContext.getMppModel(gradleModule: IdeaModule): KotlinMPPGradleModel? =
this.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java)
?.let { kotlinMppModel ->
KotlinMPPGradleProjectResolver.proxyObjectCloningCache[kotlinMppModel] as? KotlinMPPGradleModelImpl ?: KotlinMPPGradleModelImpl(
kotlinMppModel,
KotlinMPPGradleProjectResolver.proxyObjectCloningCache
).also {
KotlinMPPGradleProjectResolver.proxyObjectCloningCache[kotlinMppModel] = it
}
}
@@ -9,10 +9,20 @@ import org.jetbrains.plugins.gradle.model.ExternalDependency
import org.jetbrains.plugins.gradle.model.ModelFactory
import java.io.File
import java.io.Serializable
import java.util.*
typealias KotlinDependency = ExternalDependency
fun KotlinDependency.deepCopy(): KotlinDependency = ModelFactory.createCopy(this)
fun KotlinDependency.deepCopy(cache: MutableMap<Any, Any>): KotlinDependency {
val cachedValue = cache[this] as? KotlinDependency
if (cachedValue != null) {
return cachedValue
} else {
val result = ModelFactory.createCopy(this)
cache[this] = result
return result
}
}
interface KotlinModule : Serializable {
val name: String
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle
import java.io.File
import java.util.*
data class KotlinSourceSetImpl(
override val name: String,
@@ -18,12 +19,12 @@ data class KotlinSourceSetImpl(
val defaultIsTestModule: Boolean = false
) : KotlinSourceSet {
constructor(kotlinSourceSet: KotlinSourceSet) : this(
constructor(kotlinSourceSet: KotlinSourceSet, cloningCache: MutableMap<Any, Any>) : this(
kotlinSourceSet.name,
KotlinLanguageSettingsImpl(kotlinSourceSet.languageSettings),
HashSet(kotlinSourceSet.sourceDirs),
HashSet(kotlinSourceSet.resourceDirs),
kotlinSourceSet.dependencies.map { it.deepCopy() }.toSet(),
kotlinSourceSet.dependencies.map { it.deepCopy(cloningCache) }.toSet(),
HashSet(kotlinSourceSet.dependsOnSourceSets),
kotlinSourceSet.platform,
kotlinSourceSet.isTestModule
@@ -87,10 +88,14 @@ data class KotlinCompilationImpl(
) : KotlinCompilation {
// create deep copy
constructor(kotlinCompilation: KotlinCompilation) : this(
constructor(kotlinCompilation: KotlinCompilation, cloningCache: MutableMap<Any, Any>) : this(
kotlinCompilation.name,
kotlinCompilation.sourceSets.map { KotlinSourceSetImpl(it) }.toList(),
kotlinCompilation.dependencies.map { it.deepCopy() }.toSet(),
kotlinCompilation.sourceSets.map { initialSourceSet ->
(cloningCache[initialSourceSet] as? KotlinSourceSet) ?: KotlinSourceSetImpl(initialSourceSet, cloningCache).also {
cloningCache[initialSourceSet] = it
}
}.toList(),
kotlinCompilation.dependencies.map { it.deepCopy(cloningCache) }.toSet(),
KotlinCompilationOutputImpl(kotlinCompilation.output),
KotlinCompilationArgumentsImpl(kotlinCompilation.arguments),
ArrayList(kotlinCompilation.dependencyClasspath)
@@ -126,12 +131,16 @@ data class KotlinTargetImpl(
) : KotlinTarget {
override fun toString() = name
constructor(target: KotlinTarget) : this(
constructor(target: KotlinTarget, cloningCache: MutableMap<Any, Any>) : this(
target.name,
target.presetName,
target.disambiguationClassifier,
KotlinPlatform.byId(target.platform.id) ?: KotlinPlatform.COMMON,
target.compilations.map { KotlinCompilationImpl(it) }.toList(),
target.compilations.map { initialCompilation ->
(cloningCache[initialCompilation] as? KotlinCompilation) ?: KotlinCompilationImpl(initialCompilation, cloningCache).also {
cloningCache[initialCompilation] = it
}
}.toList(),
KotlinTargetJarImpl(target.jar?.archiveFile)
)
}
@@ -147,9 +156,18 @@ data class KotlinMPPGradleModelImpl(
override val kotlinNativeHome: String
) : KotlinMPPGradleModel {
constructor(mppModel: KotlinMPPGradleModel) : this(
mppModel.sourceSets.mapValues { KotlinSourceSetImpl(it.value) },
mppModel.targets.map { KotlinTargetImpl(it) }.toList(),
constructor(mppModel: KotlinMPPGradleModel, cloningCache: MutableMap<Any, Any>) : this(
mppModel.sourceSets.mapValues { initialSourceSet ->
(cloningCache[initialSourceSet] as? KotlinSourceSet) ?: KotlinSourceSetImpl(
initialSourceSet.value,
cloningCache
).also { cloningCache[initialSourceSet] = it }
},
mppModel.targets.map { initialTarget ->
(cloningCache[initialTarget] as? KotlinTarget) ?: KotlinTargetImpl(initialTarget, cloningCache).also {
cloningCache[initialTarget] = it
}
}.toList(),
ExtraFeaturesImpl(mppModel.extraFeatures.coroutinesState),
mppModel.kotlinNativeHome
)