Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache provided types in the compiler #14754

Open
kerams opened this issue Feb 15, 2023 · 2 comments
Open

Cache provided types in the compiler #14754

kerams opened this issue Feb 15, 2023 · 2 comments

Comments

@kerams
Copy link
Contributor

kerams commented Feb 15, 2023

I propose we cache provided types on demand in the compiler itself.

Type providers commonly use caching to avoid regenerating types when static arguments remain the same. This significantly improves the responsiveness of Intellisense for heavy type providers. However, the back and forth facaded type conversions are still present. The situation is further exacerbated for generative type providers, where temporary assemblies need to be generated and written to disk on every keystroke.

Type provider authors should be able to indicate (via a parameter), that the compiler may cache provided types internally. The compiler would then retain the final, processed representations of provided types, and not call the type provider to apply (method or type) static arguments unless the latter have changed. Care would need to be taken in order to properly clean up unused data from caches to avoid memory leaks.

Related #4706, perhaps #5931.

@T-Gro
Copy link
Member

T-Gro commented Feb 28, 2023

  1. Would the cache key be defined by a tuple containing all static parameters?
  2. More important, how would the information flow work in case of cache invalidation without changing static args?
    (never invalidated? or a separate method on TP to check staleness?)

For the clean-up part, I think a time-based expiration refreshed on read-access could work here.

@smoothdeveloper
Copy link
Contributor

Just sharing few cobbled up thoughts (I use FSharp.Data.SqlClient extensively, and also FSharp.Data):

Would the cache key be defined by a tuple containing all static parameters?

I got the intuition this is all boiled down to a string already, which I can see in tooltip when I hover a TP instanciation.

More important, how would the information flow work in case of cache invalidation without changing static args?
(never invalidated? or a separate method on TP to check staleness?)

In my experience, this is already broken in VS, it is never updated, unless tweaking the static args, things are never refreshed, even if I issue a build.

It changed to this mostly along the VS 2019 timeline, and I think it was done to alleviate memory & performance issues with the 32bit process.

I'd prefer the baseline to be less aggressively caching (so it is possible to refresh without closing / reopening, or tweaking the static args), maybe rechecking when user pops intellisense on generated types, based on something inverse to how long last type check of the TP instantiation took, and then having a focus to lift out the caching requirement from the TP implementation itself come second (I know it contradicts with what this suggestion is about).

Type Providers that don't update are more confusing to end users, and the performance issues of pre 2019 era aren't as drastic on so many aspects that it is worth considering the UX for consumers (that may not be F# experts), and then making it better for TP authors (so they have nothing to do related to caching, as default).

Another consideration would be to have a way from the TP implementation to invalidate the type through a callback or alternative mechanism; providing helpers for such infrastructure, related to filesystem, would make a lot of sense also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: New
Development

No branches or pull requests

3 participants