[Java.Interop] ReadOnlyProperty<T>? #1249
Draft
+122
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Context: #1243
Context: #1248
Java's
final
keyword is contextual, and maps to (at least?) three separate keywords in C#:const
on fieldsreadonly
on fieldssealed
on types and methodsWhen binding fields, we only support "const"
final
fields: fields for which the value is known at compile-time.Non-
const
fields are bound as properties, requiring a lookup for every property access.This can be problematic, performance-wise, as
final
fields without a compile-time value only need to be looked up once; afterward, their value cannot change 1. As such, we should consider altering our binding of "readonly" static properties to cache the value.PR #1248 implemented a "nullable"-based approach to caching the field value. While this approach works for reference types, it is likely not thread safe for
int?
and other value types.There is a comment on #1248 to make the approach thread-safe, but @jonpryor isn't entirely sure if it's correct. The "straightfoward" approach would be to use a C#
lock
statement, but that requires a GC-allocated lock object, which would increase memory use. Furthermore, if this code is wrong, the only way to fix it is by regenerating the bindings.@jonpryor considered moving the thread-safety logic into a separate type, moving it outside of the generated code. This is implemented as
ReadOnlyProperty<T>
, in this commit.To help figure this out, along with the performance implications, add a
ReadOnlyPropertyTiming
test fixture toJava.Interop-PerformanceTests.dll
to measure performance, and updateJavaTiming
to have the various proposed binding ideas so that we can determine the resulting code size.Results are as follows:
ReadOnlyProperty<T>
cachingWorst performance is to not cache anything. At least the expected behavior is verified.
"Nullable" caching is quite performant. Pity it isn't thread-safe.
"Inlined thread-safe caching" is ~20% faster than "nullable" caching.
ReadOnlyProperty<T>
caching is nearly 2x slower than "nullable".Can
ReadOnlyProperty<T>
be made faster?Footnotes
Not strictly true; instance fields can change within the
object constructor, and static fields change change within
the static constructor. As [generator] Cache static final field values. #1248 is about static fields of
bound types, there should be no way for us to observe this.
Things become trickier with instance fields. ↩