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

Add ReadOnly iterators and refactor other iterators #329

Conversation

fxamacker
Copy link
Member

@fxamacker fxamacker commented Jul 18, 2023

Updates #292

Changes:

  • Adds ReadOnly iterators that match current iterator API (except for the "ReadOnly" suffix added to some function names).
  • Refactors API of non-Readonly iterators because register inlining will require more parameters for MapIterator.

For ReadOnly iterators, the caller is responsible for preventing changes to child containers during iteration because mutations of child containers are not guaranteed to persist.

For non-ReadOnly iterators, two additional parameters are needed to update child container in parent map when child container is modified.


  • Targeted PR against main branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work
  • Code follows the standards mentioned here
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

This change:
- Adds ReadOnly iterators that match current iterator API
  (except for the "ReadOnly" suffix added to some function names).
- Refactors API of non-Readonly iterators because register
  inlining will require more parameters for MapIterator.

For ReadOnly iterators, the caller is responsible for preventing
changes to child containers during iteration because mutations
of child containers are not guaranteed to persist.

For non-ReadOnly iterators, two additional parameters are needed to
update child container in parent map when child container is modified.
@fxamacker fxamacker added the breaking change changes to API that can break programs using Atree's API label Jul 18, 2023
@fxamacker fxamacker requested a review from ramtinms as a code owner July 18, 2023 20:33
@fxamacker fxamacker self-assigned this Jul 18, 2023
@fxamacker fxamacker requested a review from turbolent as a code owner July 18, 2023 20:33
@@ -65,7 +65,7 @@ func verifyArray(

// Verify array elements by iterator
i := 0
err = array.Iterate(func(v Value) (bool, error) {
err = array.IterateReadOnly(func(v Value) (bool, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any tests that still utilize the old APIs, like Iterate, IterateRange, etc.?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, the old is the same as new API implementation until register inlining is added. So (for now) the tests for the new APIs currently cover the old functionality.

The old APIs like Iterate and IterateRange, etc. currently have an incomplete implementation regarding register inlining, so the tests for them will be done after they are implemented.

// ReadOnlyIterator returns readonly iterator for array elements.
// If elements of child containers are mutated, those changes
// are not guaranteed to persist.
func (a *Array) ReadOnlyIterator() (*ArrayIterator, error) {
Copy link
Member

@SupunS SupunS Jul 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More of a question on use-cases: What is the advantage of using the read-only iterators over the non-read-only ones? Is there a performance gain?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good questions. From performance & API perspectives:

  • performance: non-readonly iterator needs to keep track of child mutable elements so when child elements are modified, parent container would re-inline them. So there is overhead and additional data for tracking, etc.

  • API: array iterators (readonly and non-readonly) would remain the same. However, non-readonly map iterators need additional parameters to generate hash for map key and compare map key. I think there are enough use cases for client code iterating elements without changes, so requiring these extra parameters is overkill.

Most likely, I'll postpone merging this PR until after register inlining is implemented (in a separate PR). So we'll have a chance to tweak the API if needed before this PR is merged.

Copy link
Contributor

@ramtinms ramtinms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have that much context on the requirements from the Cadence side, but the code logic described in the text matches the code and the code looks good to me.

Copy link
Member

@turbolent turbolent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in the review session today, this looks good, and while there are pretty much no cases where these functions are useful for Cadence programs, they are useful for many cases where Cadence itself iterates and does not mutate.

I assume the PR is not actually a breaking change and only adds the new Read... functions?
Ideally the PR should not change the behavior of the existing iteration functions and keep assuming the callback might mutate. This way Cadence keeps working and can start to adopt the read-only iterators where it makes sense and is safe.

@turbolent
Copy link
Member

@fxamacker Could you please open a tech-debt follow-up issue in the Cadence repo, so that we don't forget to switch Cadence to the new read-only versions where possible?

@fxamacker
Copy link
Member Author

I'm replacing this PR with a new one that supports mutation of values from non-readonly iterators. The replacement PR will also include the atree inlining changes from PR #342.

A followup issue will also be opened in onflow/cadence repo.

@fxamacker fxamacker closed this Sep 29, 2023
@fxamacker
Copy link
Member Author

This PR is replaced by PR #345

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change changes to API that can break programs using Atree's API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants