IJPL-237264 Optimize replaceBySource for root entities without symbolic id

(cherry picked from commit ef3ca691f15c4ca6ea69e39fedd54a767df57545)

IJ-MR-194156

GitOrigin-RevId: 9736bc2670726b72b44cdbfb6d416e8cf63456df
This commit is contained in:
Liudmila Kornilova
2026-03-04 07:45:50 +00:00
committed by intellij-monorepo-bot
parent f71ecb1a84
commit bc460c94e5
3 changed files with 29 additions and 9 deletions
@@ -48,6 +48,7 @@ import com.intellij.platform.workspace.storage.testEntities.entities.OoChildWith
import com.intellij.platform.workspace.storage.testEntities.entities.OoParentEntity
import com.intellij.platform.workspace.storage.testEntities.entities.ParentEntity
import com.intellij.platform.workspace.storage.testEntities.entities.ParentMultipleEntity
import com.intellij.platform.workspace.storage.testEntities.entities.WithSoftLinkEntity
import com.intellij.platform.workspace.storage.testEntities.entities.modifyNamedChildEntity
import com.intellij.platform.workspace.storage.testEntities.entities.modifyNamedEntity
import com.intellij.platform.workspace.storage.testEntities.entities.modifyOoChildWithNullableParentEntity
@@ -229,6 +230,24 @@ class WorkspaceModelBenchmarksPerformanceTest {
.attempts(1).start()
}
@Test
fun replaceBySourceALotOfRootEntitiesWithoutSymbolicId(testInfo: TestInfo) {
val source: MutableEntityStorage = MutableEntityStorage.create()
val target: MutableEntityStorage = MutableEntityStorage.create()
val size = 30_000
repeat(size) {
source addEntity WithSoftLinkEntity(NameId("$it"), MySource) // could be any entity without symbolic id
target addEntity WithSoftLinkEntity(NameId("$it"), MySource)
}
Benchmark.newBenchmark(testInfo.displayName) {
target.replaceBySource({ true }, source.toSnapshot())
}
.warmupIterations(0)
.attempts(1).start()
}
@Test
fun serializeCommunityProject(testInfo: TestInfo) {
val storageBuilder = MutableEntityStorage.create()
@@ -203,7 +203,9 @@ internal class MutableEntityStorageImpl(
override fun <E : WorkspaceEntity> entities(entityClass: Class<E>): Sequence<E> = getEntitiesTimeMs.addMeasuredTime {
@Suppress("UNCHECKED_CAST")
entitiesByType[entityClass.toClassId()]?.all()?.map { it.createEntity(this) } as? Sequence<E> ?: emptySequence()
entitiesByType[entityClass.toClassId()]?.all()?.map {
it.createEntity(this) // we have to wrap entity data with the link to the entity storage to be able to resolve parent/children
} as? Sequence<E> ?: emptySequence()
}
override fun <E : WorkspaceEntityWithSymbolicId, R : WorkspaceEntity> referrers(
@@ -914,14 +914,13 @@ internal class ReplaceBySourceAsTree {
}
else {
val oppositeEntityData = oppositeStorage.entityDataByIdOrDie(rootEntity.id)
goalStorage.entities(rootEntity.id.clazz.findWorkspaceEntity())
.filter {
val itId = (it as WorkspaceEntityBase).id
if (goalState[itId] != null) return@filter false
goalStorage.entityDataByIdOrDie(itId).equalsByKey(oppositeEntityData) && goalStorage.refs.getParentRefsOfChild(itId.asChild())
.isEmpty()
}
.firstOrNull()
val entityClass = rootEntity.id.clazz.findWorkspaceEntity()
val data = goalStorage.entitiesByType[entityClass.toClassId()]?.all()?.firstOrNull { entityData ->
if (!entityData.equalsByKey(oppositeEntityData)) return@firstOrNull false
val itId = entityData.createEntityId()
goalState[itId] == null && goalStorage.refs.getParentRefsOfChild(itId.asChild()).isEmpty()
}
data?.createEntity(goalStorage)
}
}
}