Performance: sped up type analyzer by 5-25% by caching types that have been converted to or from an instance. This drops the analysis time of pydantic from 17s to 12s.

This commit is contained in:
Eric Traut 2023-03-16 08:15:56 -06:00
parent 2ca9a8af4a
commit 99c73a0f7d
2 changed files with 32 additions and 1 deletions

View File

@ -2008,6 +2008,11 @@ export function isEffectivelyInstantiable(type: Type): boolean {
}
export function convertToInstance(type: Type, includeSubclasses = true): Type {
// See if we've already performed this conversion and cached it.
if (type.cached?.instanceType) {
return type.cached.instanceType;
}
let result = mapSubtypes(type, (subtype) => {
switch (subtype.category) {
case TypeCategory.Class: {
@ -2062,10 +2067,21 @@ export function convertToInstance(type: Type, includeSubclasses = true): Type {
);
}
// Cache the converted value for next time.
if (!type.cached) {
type.cached = {};
}
type.cached.instanceType = result;
return result;
}
export function convertToInstantiable(type: Type): Type {
// See if we've already performed this conversion and cached it.
if (type.cached?.instantiableType) {
return type.cached.instantiableType;
}
let result = mapSubtypes(type, (subtype) => {
switch (subtype.category) {
case TypeCategory.Class: {
@ -2100,6 +2116,12 @@ export function convertToInstantiable(type: Type): Type {
);
}
// Cache the converted value for next time.
if (!type.cached) {
type.cached = {};
}
type.cached.instantiableType = result;
return result;
}

View File

@ -148,6 +148,13 @@ interface TypeBase {
// with a TypeFlags because we don't want an ambiguous and unambiguous
// type to be seen as distinct when comparing types.
isAmbiguous?: boolean;
// Cached values are not cloned.
cached?: {
// Type converted to instantiable and instance (cached)
instantiableType?: Type;
instanceType?: Type;
};
}
export namespace TypeBase {
@ -176,7 +183,9 @@ export namespace TypeBase {
}
export function cloneType<T extends TypeBase>(type: T): T {
return { ...type };
const clone = { ...type };
delete clone.cached;
return clone;
}
export function cloneTypeAsInstance<T extends TypeBase>(type: T): T {