Skip to content

Commit

Permalink
1.3.21 优化性能与内存占用 - 优化各种路径模型类
Browse files Browse the repository at this point in the history
  • Loading branch information
DragonKnightOfBreeze committed Sep 11, 2024
1 parent 3da18c2 commit 1237889
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 129 deletions.
61 changes: 30 additions & 31 deletions src/main/kotlin/icu/windea/pls/lang/util/CwtConfigManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,14 @@ object CwtConfigManager {
private fun doGetConfigType(element: CwtMemberElement): CwtConfigType? {
val configPath = element.configPath
if(configPath == null || configPath.isEmpty()) return null
val path = configPath.path
return when {
element is CwtProperty && path.matchesAntPattern("types/type[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("types/type[*]") -> {
CwtConfigType.Type
}
element is CwtProperty && path.matchesAntPattern("types/type[*]/subtype[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("types/type[*]/subtype[*]") -> {
CwtConfigType.Subtype
}
element is CwtProperty && path.matchesAntPattern("types/type[*]/modifiers/**") -> {
element is CwtProperty && configPath.path.matchesAntPattern("types/type[*]/modifiers/**") -> {
when {
configPath.get(3).surroundsWith("subtype[", "]") -> {
if(configPath.length == 5) return CwtConfigType.Modifier
Expand All @@ -135,28 +134,28 @@ object CwtConfigManager {
}
null
}
element is CwtProperty && path.matchesAntPattern("enums/enum[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("enums/enum[*]") -> {
CwtConfigType.Enum
}
element is CwtValue && path.matchesAntPattern("enums/enum[*]/*") -> {
element is CwtValue && configPath.path.matchesAntPattern("enums/enum[*]/*") -> {
CwtConfigType.EnumValue
}
element is CwtProperty && path.matchesAntPattern("enums/complex_enum[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("enums/complex_enum[*]") -> {
CwtConfigType.ComplexEnum
}
element is CwtProperty && path.matchesAntPattern("values/value[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("values/value[*]") -> {
CwtConfigType.DynamicValueType
}
element is CwtValue && path.matchesAntPattern("values/value[*]/*") -> {
element is CwtValue && configPath.path.matchesAntPattern("values/value[*]/*") -> {
CwtConfigType.DynamicValue
}
element is CwtProperty && path.matchesAntPattern("inline[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("inline[*]") -> {
CwtConfigType.Inline
}
element is CwtProperty && path.matchesAntPattern("single_alias[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("single_alias[*]") -> {
CwtConfigType.SingleAlias
}
element is CwtProperty && path.matchesAntPattern("alias[*]") -> {
element is CwtProperty && configPath.path.matchesAntPattern("alias[*]") -> {
val aliasName = configPath.get(0).substringIn('[', ']', "").substringBefore(':', "")
when {
aliasName == "modifier" -> return CwtConfigType.Modifier
Expand All @@ -165,61 +164,61 @@ object CwtConfigManager {
}
CwtConfigType.Alias
}
element is CwtProperty && path.matchesAntPattern("links/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("links/*") -> {
CwtConfigType.Link
}
element is CwtProperty && path.matchesAntPattern("localisation_links/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("localisation_links/*") -> {
CwtConfigType.LocalisationLink
}
element is CwtProperty && path.matchesAntPattern("localisation_promotions/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("localisation_promotions/*") -> {
CwtConfigType.LocalisationPromotion
}
element is CwtProperty && path.matchesAntPattern("localisation_commands/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("localisation_commands/*") -> {
CwtConfigType.LocalisationCommand
}
element is CwtProperty && path.matchesAntPattern("modifier_categories/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("modifier_categories/*") -> {
CwtConfigType.ModifierCategory
}
element is CwtProperty && path.matchesAntPattern("modifiers/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("modifiers/*") -> {
CwtConfigType.Modifier
}
element is CwtProperty && path.matchesAntPattern("scopes/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("scopes/*") -> {
CwtConfigType.Scope
}
element is CwtProperty && path.matchesAntPattern("scope_groups/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("scope_groups/*") -> {
CwtConfigType.ScopeGroup
}
element is CwtProperty && path.matchesAntPattern("database_object_types/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("database_object_types/*") -> {
CwtConfigType.DatabaseObjectType
}
element is CwtProperty && path.matchesAntPattern("system_scopes/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("system_scopes/*") -> {
CwtConfigType.SystemScope
}
element is CwtProperty && path.matchesAntPattern("localisation_locales/*") -> {
element is CwtProperty && configPath.path.matchesAntPattern("localisation_locales/*") -> {
CwtConfigType.LocalisationLocale
}
path.matchesAntPattern("scripted_variables/*") -> {
configPath.path.matchesAntPattern("scripted_variables/*") -> {
CwtConfigType.ExtendedScriptedVariable
}
path.matchesAntPattern("definitions/*") -> {
configPath.path.matchesAntPattern("definitions/*") -> {
CwtConfigType.ExtendedDefinition
}
path.matchesAntPattern("game_rules/*") -> {
configPath.path.matchesAntPattern("game_rules/*") -> {
CwtConfigType.ExtendedGameRule
}
path.matchesAntPattern("on_actions/*") -> {
configPath.path.matchesAntPattern("on_actions/*") -> {
CwtConfigType.ExtendedOnAction
}
path.matchesAntPattern("inline_scripts/*") -> {
configPath.path.matchesAntPattern("inline_scripts/*") -> {
CwtConfigType.ExtendedInlineScript
}
path.matchesAntPattern("parameters/*") -> {
configPath.path.matchesAntPattern("parameters/*") -> {
CwtConfigType.ExtendedParameter
}
path.matchesAntPattern("complex_enum_values/*/*") -> {
configPath.path.matchesAntPattern("complex_enum_values/*/*") -> {
CwtConfigType.ExtendedComplexEnumValue
}
path.matchesAntPattern("dynamic_values/*/*") -> {
configPath.path.matchesAntPattern("dynamic_values/*/*") -> {
CwtConfigType.ExtendedDynamicValue
}
else -> null
Expand Down
41 changes: 33 additions & 8 deletions src/main/kotlin/icu/windea/pls/model/CwtConfigPath.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,57 @@ interface CwtConfigPath : Iterable<String> {

fun isEmpty(): Boolean = length == 0
fun isNotEmpty(): Boolean = length != 0
fun get(index: Int): String = this.subPaths.getOrNull(index).orEmpty()
fun get(index: Int): String = subPaths.getOrNull(index).orEmpty()

override fun iterator(): Iterator<String> = this.subPaths.iterator()
override fun iterator(): Iterator<String> = subPaths.iterator()

companion object Resolver {
val Empty: CwtConfigPath = EmptyCwtConfigPath

fun resolve(path: String): CwtConfigPath = doResolve(path)

fun resolve(subPaths: List<String>): CwtConfigPath = doResolve(subPaths)
}
}

//Implementations (interned)
//Implementations (not interned)

private fun doResolve(path: String): CwtConfigPath {
if(path.isEmpty()) return EmptyCwtConfigPath
return CwtConfigPathImpl(path)
}

private fun doResolve(subPaths: List<String>): CwtConfigPath {
if(subPaths.isEmpty()) return EmptyCwtConfigPath
return CwtConfigPathImpl(subPaths)
}

//12 + 2 * 4 = 20 -> 24
private class CwtConfigPathImpl(
subPaths: List<String>
) : CwtConfigPath {
override val path: String = subPaths.joinToString("/") { it.replace("/", "\\/") }.intern()
override val subPaths: List<String> = subPaths.map { it.intern() }
private class CwtConfigPathImpl : CwtConfigPath {
override val path: String
override val subPaths: List<String>
override val length: Int get() = subPaths.size

constructor(path: String) {
this.path = path
this.subPaths = path2SubPaths(path)
}

constructor(subPaths: List<String>) {
this.path = subPaths2Path(subPaths)
this.subPaths = subPaths
}

private fun path2SubPaths(path: String): List<String> {
//use simple implementation
return path.replace("\\/", "\u0000").split('/').map { it.replace('\u0000', '/') }
}

private fun subPaths2Path(subPaths: List<String>): String {
//use simple implementation
return subPaths.joinToString("/") { it.replace("/", "\\/") }
}

override fun equals(other: Any?) = this === other || other is CwtConfigPath && path == other.path
override fun hashCode() = path.hashCode()
override fun toString() = path
Expand Down
121 changes: 59 additions & 62 deletions src/main/kotlin/icu/windea/pls/model/ParadoxExpressionPath.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,44 +82,79 @@ fun ParadoxExpressionPath.matchEntire(other: List<String>, ignoreCase: Boolean =
return true
}

//Implementations (interned)
//Implementations (not interned)

private fun doResolve(originalPath: String): ParadoxExpressionPath {
if(originalPath.isEmpty()) return EmptyParadoxExpressionPath
return ParadoxExpressionPathImplA(originalPath)
return ParadoxExpressionPathImpl(originalPath)
}

private fun doResolve(originalSubPaths: List<String>): ParadoxExpressionPath {
if(originalSubPaths.isEmpty()) return EmptyParadoxExpressionPath
return ParadoxExpressionPathImplB(originalSubPaths)
return ParadoxExpressionPathImpl(originalSubPaths)
}

//to optimize memory, it's better to use cache, or make property 'path' and 'originalPath' computed

//12 + 4 * 4 = 28 -> 32
private class ParadoxExpressionPathImplA(
path: String
) : ParadoxExpressionPath {
override val originalPath: String = path.intern()
override val originalSubPaths: List<String> = path2SubPaths(path)
override val subPaths: List<String> = originalSubPaths.map { it.unquote().intern() }
override val path: String = subPaths2Path(subPaths)
private class ParadoxExpressionPathImpl : ParadoxExpressionPath {
override val path: String
override val subPaths: List<String>
override val originalPath: String
override val originalSubPaths: List<String>
override val length: Int get() = subPaths.size

override fun equals(other: Any?) = this === other || other is ParadoxExpressionPath && path == other.path
override fun hashCode() = path.hashCode()
override fun toString() = path
}

//12 + 4 * 4 = 28 -> 32
private class ParadoxExpressionPathImplB(
originalSubPaths: List<String>
) : ParadoxExpressionPath {
override val originalSubPaths: List<String> = originalSubPaths.map { it.intern() }
override val originalPath: String = subPaths2Path(originalSubPaths)
override val subPaths: List<String> = originalSubPaths.map { it.unquote().intern() }
override val path: String = subPaths2Path(subPaths)
override val length: Int get() = originalSubPaths.size
constructor(originalPath: String) {
this.originalPath = originalPath
this.originalSubPaths = path2SubPaths(originalPath)
val mayBeQuoted = originalPath.contains('"')
this.subPaths = if(mayBeQuoted) originalSubPaths.map { it.unquote() } else originalSubPaths
this.path = if(mayBeQuoted) subPaths2Path(subPaths) else originalPath
}

constructor(originalSubPaths: List<String>) {
this.originalPath = subPaths2Path(originalSubPaths)
this.originalSubPaths = originalSubPaths
val mayBeQuoted = originalPath.contains('"')
this.subPaths = if(mayBeQuoted) originalSubPaths.map { it.unquote() } else originalSubPaths
this.path = if(mayBeQuoted) subPaths2Path(subPaths) else originalPath
}

private fun path2SubPaths(path: String): List<String> {
return buildList {
val builder = StringBuilder()
var escape = false
path.forEach { c ->
when {
c == '\\' -> {
escape = true
}
c == '/' && !escape -> {
if(builder.isNotEmpty()) add(builder.toString())
builder.clear()
}
else -> {
if(escape) escape = false
builder.append(c)
}
}
}
if(builder.isNotEmpty()) add(builder.toString())
}
}

private fun subPaths2Path(subPaths: List<String>): String {
val builder = StringBuilder()
var isFirst = true
subPaths.forEach { p ->
if(isFirst) isFirst = false else builder.append('/')
p.forEach { c ->
if(c == '/') builder.append('\\')
builder.append(c)
}
}
return builder.toString()
}

override fun equals(other: Any?) = this === other || other is ParadoxExpressionPath && path == other.path
override fun hashCode() = path.hashCode()
Expand All @@ -137,41 +172,3 @@ private object EmptyParadoxExpressionPath : ParadoxExpressionPath {
override fun hashCode() = path.hashCode()
override fun toString() = path
}

private fun path2SubPaths(path: String): List<String> {
return buildList {
val builder = StringBuilder()
var escape = false
path.forEach { c ->
when {
c == '\\' -> {
escape = true
}
c == '/' && !escape -> {
add(builder.toString().intern())
builder.clear()
}
else -> {
if(escape) escape = false
builder.append(c)
}
}
}
if(builder.isNotEmpty()) {
add(builder.toString().intern())
}
}
}

private fun subPaths2Path(originalSubPaths: List<String>): String {
val builder = StringBuilder()
var isFirst = true
originalSubPaths.forEach { p ->
if(isFirst) isFirst = false else builder.append('/')
p.forEach { c ->
if(c == '/') builder.append('\\')
builder.append(c)
}
}
return builder.toString().intern()
}
Loading

0 comments on commit 1237889

Please sign in to comment.