I’m profiling my KSP processor and seeing that KSP...
# ksp
v
I’m profiling my KSP processor and seeing that KSP spends a lot of time visiting classes’ props and funs declarations. The annotation I’m using is only applicable to types, so it is waste of time to scan props and funs. I understand that current processor’s API doesn’t help to avoid that since there is no way to know which annotations are used by the processor and configure
CollectAnnotatedSymbolsVisitor
appropriately. But maybe you think it is a good idea to introduce an
annotations()
fun like javac processors have and infer what exactly should be visited with given set of KSP processors and all annotations they aim to use?
j
Thanks for doing the profiling! For the collecting annotated symbols part, KSP has done several optimizations already, including filtering out annotations based on short names to avoid resolving unnecessary types. For your profiling, it might be worthing to know how much time is spent on visiting vs how much time is spent for resolution. Generally for KSP, visiting should not take a major part of execution time, it is actually resolving types that is taking the most time, type resolution is generally more expensive than just visiting syntactical structures.
v
I think there is a misunderstanding. I’m talking about these two lines of code. It doesn’t make any sense to traverse anything except
ClassDeclaration
for my processor since its annotation will never be placed anywhere but type itself.
getSymbolsWithAnnotation
spends 95%+ of time traversing properties, function declarations, etc. When I only need
ClassDeclarations
traversed. I think that it could be avoided if KSP knew upfront where annotations used by its
SymbolProcessors
could be possibly used.
Ok, maybe it is makes sense to traverse declarations but only other nested
ClassDeclarations
🙂
j
got it. It might be an optimization opportunity, but for general correctness current approach is still needed. Maybe we can consider allowing customizable visitors for collecting symbols so that you can write your own visitor for your use case (Actually you can also do it now, I think you should have access to all necessary APIs, take the implementation in
ResolverImpl
as a reference)
v
Do you think it is not feasible to change
SymbolProcessor
API? Mind me making a PR with this optimization? I think it is possible to change
SymbolProcessor
api without breaking backwards compatibility
j
you can explain your proposal here before jumping into implementation.
v
Sure. I think it is possible to add
fun usedAnnotations(): Set<String> = emptySet()
method to the
SymbolProcessor
interface. Here it is possible to gather all used annotations from all processors and configure resolver accordingly so it will skip declarations that doesn’t make sense to traverse by configuring
CollectAnnotatedSymbolsVisitor
Something like this. Right now I’m implementing my own resolver with this optimization (as you suggested) for my specific case after that I’ll be able to measure perf gain on our project. I’m not that confident in my profilig skills, but the scale of our build should help me measure pure perf gain anyways 🙂 Will keep you posted.
j
sure, looking forward to the profiling result. 🙂
v
Meh… the improvement turned out to be too small, around 1%, not worth it.