Skip to content

🟡 [Performance] ObjectModel built repeatedly for same types across endpoints #670

@tangcent

Description

@tangcent

Problem

The JsonConstructionCache used in DefaultPsiClassHelper.buildTypeObject() is local to a single buildObjectModel call. When the same type (e.g., UserInfo) appears as a request body in one endpoint and as a response body in another, the entire ObjectModel is rebuilt from scratch — including recursive type resolution, field extraction, and rule evaluation for every field.

For example, if ResponseEntity<UserInfo> is the return type of 20 endpoints, UserInfo's ObjectModel is built 20 times.

Impact

For projects with shared DTOs used across many endpoints, this causes significant redundant work. Each ObjectModel build involves:

  • PSI class resolution
  • Generic type substitution
  • Rule evaluation for every field (FIELD_IGNORE, FIELD_NAME, FIELD_DOC, FIELD_REQUIRED, FIELD_DEFAULT_VALUE, FIELD_MOCK, FIELD_DEMO, FIELD_ADVANCED, JSON_RULE_CONVERT)
  • Recursive processing of nested types

Estimated speedup: 1.2-1.5x for projects with repeated types

Fix

Introduce a project-level or scan-session-level cache keyed by (qualifiedName, option) that persists across buildObjectModel calls:

@Service(Service.Level.PROJECT)
class DefaultPsiClassHelper(private val project: Project) : PsiClassHelper {

    private val modelCache = ConcurrentHashMap<String, ObjectModel?>()

    override suspend fun buildObjectModel(
        psiClass: PsiClass,
        option: Int,
        maxDepth: Int
    ): ObjectModel? {
        val qualifiedName = psiClass.qualifiedName ?: return null
        val cacheKey = "$qualifiedName@$option"

        modelCache[cacheKey]?.let { return it }

        val result = buildTypeObject(psiClass, ...)

        if (result != null) {
            modelCache[cacheKey] = result
        }
        return result
    }
}

The cache should be invalidated when source files change (can hook into ApiFileChangeListener).

Location

  • src/main/kotlin/com/itangcent/easyapi/psi/DefaultPsiClassHelper.kt:98-127

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions