Measure the time for type inference when compiling

Is there a way to measure the time it takes for type inference when compiling?

I tried

  • gradle build --scan
  • kotlin build report

However, both only show the total compilation time and do not show compilation details.


What’s this for?

If you’re expecting to show that type inference takes a significant amount of time (as compared to all the other things the compiler does), then I suspect you’d be disappointed — but I don’t have any figures either way.

You might try comparing the compilation time of a reasonable-size program, once with no unnecessary types specified, and again after adding in explicit types for all functions/properties/variables. If the latter is faster, then the difference would (presumably) be down to the time saving from avoiding type inference.

But, as with all benchmarks, you’d have to compile them both many times, interleaved, to try to exclude variation due to memory and disk caching etc. And in this case, you’d also have to take into account the extra processing the compiler’s doing on the explicit types, the extra disk and memory they take up, etc. And also that you can’t stop the compiler doing further type inference whenever you call methods or property accessors, or do null checks, in preparation for smart-casting.

Thanks to reply.

In one lecture, it was said that the type should always be specified in kotlin because the cost of type inference is very high. It didn’t seem to make sense, so I tried to test it myself.
He said he could check it right away by checking the build timeline, so I thought there was a way to measure the time, but if not, I guess I don’t have to believe him.

I think you’re wise not to accept everything you hear in lectures without checking… :slight_smile:

As I said, I don’t know for certain, either. In fact, I’d be surprised if explicit type annotations save the compiler any work at all. After all, it still needs to work out the type of each expression anyway: for a method/variable with no explicit type, it can simply infer the expression’s type; whereas if there is an explicit type, it will have to make a further check that they’re assignment-compatible.

However, (as is often the case) intuition can be wrong, and you’d have to test it to be sure.

I’m not aware of any ‘build timeline’ that would tell you internal compiler details. (The only build timelines I’ve seen are at a higher level, showing invocations of the compiler for different modules along with other build tools.) And I doubt that type inference would be a separate compilation stage, taking a discrete interval of time that could be displayed. I think you’d need to do some A–B testing as I mentioned before.

However, even if it did take noticeably longer to compile code with lots of inferred types, would that be a good reason to avoid them? I’d say: no! There’s very often a trade-off between thinking time, compile time, and run time — and over the years, as compilers/optimisers/etc. have got better and computers more powerful, compilation time has become a smaller and smaller fraction of the time spent working on and thinking about the code. Instead, it has become more and more important to write clear, clean, safe code that’s easy to write correctly, easy to read and understand, and easy to maintain and fix and build on.

Now, you could argue whether explicit types make code cleaner or safer. Do they add sufficient clarity and robustness to justify the extra characters? (For me, I think it depends. For example, methods that are part of a public API are probably worth giving explicit types: that ensures that their types can’t change accidentally (e.g. if changes elsewhere affect the type of their expression body). And of course sometimes you want a supertype of the inferred type (e.g. to hide implementation details). However, for local variables, and private methods, explicit types may not add very much; if you use an IDE, that can always tell you the inferred type — and very complex types (such as Map<SomeDataClass, MutableList<Pair<SomeOtherDataClass, AnotherClassWithALongName<SomeParameter>>>>) can really hurt readability! So for local variables and short, private methods, I often find it clearer to omit types. But that’s partly a matter of style, and I’m sure people have varying views.)

In any case, compilation time alone is hardly ever a good reason to change how you write your code. (After all, how bad would your compile times have to be — and how great the potential savings — to justify the time spent adding unnecessary type declarations???)