Type pool #9328
Replies: 3 comments 7 replies
-
I like the idea a lot. Extending the idea with a full union and atomic type cache, including composite types like arrays and simplifying comparisons should improve performance a lot more IMO. |
Beta Was this translation helpful? Give feedback.
-
If we manage to extract dynamic parts from Atomic, it may make sense to make something like singletons for simple type. Atomic/Union creation are pretty centralised already so it would not be a big change to make the constructor private and just rely on the single instance available. That would make the need for a whole pool system unnecessary |
Beta Was this translation helpful? Give feedback.
-
This makes a lot of sense to me. Is it something I can help with? (Keeping in mind I'm still pretty new to the code base.) I've started looking at psalm/src/Psalm/Internal/TypeVisitor/TypeChecker.php Lines 140 to 141 in c0e757c Intuitively this kinda makes sense to me, since you typically wouldn't ask questions like "Where are all the places in the code base I'm using To make the most of a type pool, I suppose you'd want to eliminate offset info even on these named type objects, but it seems to me there'd be a lot of benefit in covering the built-in types by themselves. I guess this work would need to target Psalm 6, since it would almost certainly contain breaking changes for plugins? |
Beta Was this translation helpful? Give feedback.
-
Problem statement
Psalm, naturally, operate on a lot of types. My intuition (and some preliminary testing) suggests that we have a lot of duplicate type instances, maybe about ten times more than strictly necessary. This leads to Psalm having to use more memory and prevents some performance optimizations.
Where do duplicates come from?
One example could be literally duplicate types used by the inspected codebase. E.g., how many instances of
TTrue
do we have during analysis? And how many do we actually need? I'd say we should ideally have just two - one with$from_docblock = true
and one with$from_docblock = false
.Idea
Instead of having multiple instances of identical types, we could have a central pool of type instances and return instances from that pool instead of creating new instances.
Possible optimizations it enables
Comparing types could be short-circuited to identity comparison. If there's only a single instance of a non-docblock
TArray<array-key, mixed>
we could first checkif ($input_type === $container_type) { return true; }
and save some CPU cycles that are otherwise wasted comparing key and value types.Why can't we do this already?
Several architectural issues are preventing the immediate implementation of this approach.
Atomic::$checked
Atomic::$offset_start
&Atomic::$offset_end
There's also a question of how this should work with the cache. We would probably need to serialize the type pool into the cache and replace all type references with some kind of pointer to the serialized pool.
What would the code look like if we implemented it?
Parts of the code that create new types would need to register the created type with the pool, and let it replace the type instance. E.g. parser would do this:
@orklah @danog @muglug do you think this is feasible and actually makes sense?
Beta Was this translation helpful? Give feedback.
All reactions