-
Notifications
You must be signed in to change notification settings - Fork 9
Concat of list's slices and concat of lists. #317
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
base: main
Are you sure you want to change the base?
Conversation
|
Dear @AStepanov25, In order to potentially merge your code in this open-source repository and therefore proceed with your contribution, we need to have your approval on DFINITY's CLA. If you decide to agree with it, please visit this issue and read the instructions there. Once you have signed it, re-trigger the workflow on this PR to see if your code can be merged. — The DFINITY Foundation |
|
Hey thanks for your contribution! I'd like to propose a simpler API that might be worth considering:
IMO
If the performance of using |
We thought about iterators, the thing is, that performance is not comparable, because Iter generates linear amount of garbage, because ?T seems to be boxed. This is the reason
Yes, we can change to accepting iters, as there are not expected to be many.
Do we actually need this function? Isn't having both redundant. |
|
We can certainly create analogy to Array with The performance of all of these hinges on the fact that the lengths of the input lists are known in advance (not necessarily the number of lists as in This PR was meant to provide the best performing function. We utilize fast internal position iteration both for reading from the input lists and for writing into the new list. Plus we use more efficient pre-allocation because we know the number of new elements coming. Here is another proposal to avoid the complex If people really have to concatenate many slices (probably a rare application) then they can still do that with a few lines utilizing |
@timohanke @AStepanov25 I wanted to compare the performance of using |
This is a good idea! But maybe we don't need the whole family of them. We should check how much faster a
I was experimenting with starting a I've noticed the |
|
Interesting benchmarks. Thanks!
I would like that kind of interface. I agree it's sufficient in practice and I hope/wish that it can be made performant. Your implementation of addCount may not be allowed as it is. We have to check the details. @AStepanov25 will know. You are doing which is a cool trick because if
above, so maybe I am not reading the code correctly. My point was that if it does continue to allocate datablocks filled with null at the end then that may cause some problems. I think the List implementation relies on the fact that there is at most one null datablock at the end. The grow and shrink logic is quite sensitive. Having an UnsafeIter that traps is better because then we don't have to switch over next() because we want to trap anyway if we go too far in the iter. But unfortunately UnsafeIter is not an established thing. So we can't really use it in the exposed interface, can we?
That's probably because List.put has a more expensive boundary check which next_set can avoid. List.get doesn't need the same boundary check because it will automatically trap at out of boundary index. Hence unsafe_next has less of an advantage here. The advantage in practice of next_over over List.put and unsafe_next over List.get can be higher than what your benchmarks shows. That's because in practice you can sometimes avoid the loop index with |
|
What about such interface: concatIters(iters : Iter<Iter>, lengths: ?Iter) : List This method will leverage lengths for speed if they are available. Or there could be two methods, one with lengths and another without. Edit: actually we need to know one sum length. |
|
Also we could break existing invariant that at the end there are no more than two totally empty data blocks and provide |
| * Update code examples in doc comments (#224, #282, #303, #315). | ||
|
|
||
| ## 0.5.0 | ||
|
|
||
| * Add `concat` of slices function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Combining with the other unreleased changes:
| * Update code examples in doc comments (#224, #282, #303, #315). | |
| ## 0.5.0 | |
| * Add `concat` of slices function. | |
| * Update code examples in doc comments (#224, #282, #303, #315). | |
| * Add `concat` of slices function (#317). |
README.md
Outdated
| ```toml | ||
| base = "0.14.4" | ||
| new-base = "0.4.0" | ||
| new-base = "0.5.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(We will do this in a separate PR)
| new-base = "0.5.0" | |
| new-base = "0.4.0" |
| [package] | ||
| name = "new-base" | ||
| version = "0.4.0" | ||
| version = "0.5.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| version = "0.5.0" | |
| version = "0.4.0" |
| /// Runtime: `O(sum_size)` where `sum_size` is the sum of the sizes of all slices. | ||
| /// | ||
| /// Space: `O(sum_size)` | ||
| public func concatSlices<T>(slices : [(List<T>, fromInclusive : Nat, toExclusive : Nat)]) : List<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could refactor to use a new type NatSlice<T> = (T, fromInclusive : Nat, toExclusive : Nat) (defined in Types.mo) for reusability in other data structures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean type NatSlice<T> = (List<T>, fromInclusive : Nat, toExclusive : Nat)?
We can do that "lazily", i.e. whenever new code that uses it arrives refactor it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was specifically thinking (T, ...) so we could use other data structures (e.g. [T]) in place of List<T>. Agreed that we can do this later if needed.
@timohanke Sorry about this confusion, my code is just an experiment, a quick prototype without a proper check. Also the code duplication between
Probably not, but hopefully the difference between the safe and unsafe |
|
I've update the issue #325. Regarding In the issue I suggested to add more usual dynamic array methods. |
@AStepanov25 The
|
This PR is a continuation of this converstion: https://forum.dfinity.org/t/motoko-base-library-changes/39766/43