google / google/built_value.dart
possible to copy already-computed memoized fields in build()?
- Dominant language
- Dart
- Stars
- 886
- Forks
- 195
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 4
Description
While profiling my application, I noticed that a supposedly memoized field was being recomputed over and over, even though the object's fields didn't change. However, the object itself changed through a call to `replace` (with identical field values as before).
The source of it seems to be that `build` does not copy the memoized fields.
I understand the danger here. Suppose we have
```dart
abstract class Value implements Built {
int get field;
@memoized
int get derived => field*2;
// boilerplate
}
var value = Value(field: 3);
print(value.derived); // prints 6
var builder = value.toBuilder();
builder.field = 30;
value = builder.build();
print(value.derived); // should print 60
```
If `build` naively copied the field `derived`, then it would still be the value 6 at the last print statement, even though we want it to be recomputed to be 60 since the non-derived `field` has changed.
Nonetheless, it would be great if the `ValueBuilder` class could detect whether any of its fields had changed since it was created, and if not, then any derived fields that have already been computed could be copied in `build` to avoid needing to re-compute them.
One way to do this would be to have `build` copy all of the derived fields by default, but for the writable field setters, on the first write to any of them, to set all the underlying derived fields to `null`. (in the example above, this would be the field named `__derived` in the generated .g.dart file). Or to be a bit more efficient, add to each `Builder` class a single `_dirty` field that's initially `false`, and is set to `true` when any setter is called, and `build()` only copies memoized fields into the new `Built` object if `_dirty == false`.
Contributor guide
Assessment
This issue has not been assessed yet.