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
Mutate newDirtyPaths instead of creating a new array every iteration #2559
Mutate newDirtyPaths instead of creating a new array every iteration #2559
Conversation
cf7485e
to
8194add
Compare
8194add
to
f5a7d9e
Compare
Hi, can I know how you test it? I remember both push.apply and concat have similar speed. (https://jsperf.com/array-concat-vs-push-2/17) Can you test another optimization like this: const dirty = Array.prototype.concat.apply(
newDirtyPath,
this.tmp.dirty.map(path => {
path = PathUtils.create(path)
return PathUtils.transform(path, operation).toArray()
})
); I remember |
Good call @zhujinxuan! I've only been testing in browser so far. I haven't spent time to set up a reliable benchmark in the Slate repo yet though. I did set up a test to simulate the behavior: https://jsperf.com/push-and-concat/3 It looks like the optimization you suggested is a winner. Please check my work if you're able to see if it accurately reflects the code. Summary: Optimization w/ concat using es6: Same as above
Optimization w/ Array.prototype.concat (Your suggestion): Fastest! |
Unfortunately, I think I spoke too soon. The test is slower in my actual slate example, so building the large array is likely slow. I'm concerned that different cases will have different results, so I'm going to keep experimenting and try to find a more reliable optimization here. |
@brendancarney Can I have a loook at the benchmark result by:
The test time is not a direct measure of benchmark, the test is related to too many things (babel parser for example), I would suggest to use slate's own benchmark. |
Sorry for the delay, I was out of town for a week. Unfortunately, I'm not sure there's a benchmark accurately reflecting my use case. Running the benchmarks show no meaningful improvements in my branch. However, I took a recent production example of a large document and tried pasting it into an editor when running the slate examples. Over several attempts with both branches, here are the rough averages: Still really slow in both cases unfortunately. I understand that we'll probably want a benchmark that shows this improvement, so I'll try to get that added soon. |
Ok so I sort of have a benchmark ready, but still trying to figure out the best way to introduce it. Currently, we run each benchmark a minimum of 100 times. This is a little problematic for this specific case because it is least performant with larger documents, and it's really really slow. So running it one hundred times is probably not great. Should we make these options configurable by benchmark? Here are the results from inserting a paragraph block 1,000 times, wrapped in
As you can see, still really really slow, but there is an improvement. |
@brendancarney The benchmark is very naive at this moment. But I think the 200% is very convincing. If you are interested, you can temporarily add a large document insert benchmark inside BTW, can you have a try on the I am a bit surprising that the paste took 18 seconds... Last year I did same test after #1661, it was taking 5 seconds (though still slow). I think I may need to investigate why when I have time. |
Hi @zhujinxuan. It turns out they are about the same. I think your suggestion is slightly more readable. Thoughts? Also, I did not commit a benchmark because it would be ridiculously slow with the current setup. To test the speed difference, you can cut and paste the large document example in master, and then in here. |
@brendancarney As there is insignificant difference between Update: I was wrong, the concat version seems more readable. |
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.
Hey @brendancarney thanks for this! Looks great to me. Just added one thing to fix inline and then I'm good to merge.
this.tmp.dirty = dirty | ||
|
||
const dirty = this.tmp.dirty.map(path => | ||
PathUtils.transform(PathUtils.create(path), operation).toArray() |
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.
Is there any reason for collapsing this into a one-liner? Could you re-expand it to be multiple lines like it was previously? I've found that having one-liners like this makes it harder to debug, since setting breakpoints to check values isn't as easy.
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.
For sure!
6a20d3b
to
73aac6f
Compare
Thanks @brendancarney! |
Is this adding or improving a feature or fixing a bug?
Performance.
What's the new behavior?
Mutate
newDirtyPaths
on each iteration instead of copying it. For my unscientific paste test, this brings a 4s paste to about 2.5s.Have you checked that...?
yarn test
.yarn lint
. (Fix errors withyarn prettier
.)yarn watch
.)