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

Fixed #1055 #1064

Merged
merged 7 commits into from
Jan 8, 2018
Merged

Fixed #1055 #1064

merged 7 commits into from
Jan 8, 2018

Conversation

mpilquist
Copy link
Member

@mpilquist mpilquist commented Jan 8, 2018

Changed how automatic scope creation is done. Instead of inserting
scopes on the Pull => Stream boundary, they are now inserted on ++.

Introduced appendWithoutScope for cases in which scope insertion at
append time would be prohbitively expensive.

Scopes are only inserted automatically as a result of calling handleErrorWith.

Changed how automatic scope creation is done. Instead of inserting
scopes on the Pull => Stream boundary, they are now inserted on ++.

Introduced `appendWithoutScope` for cases in which scope insertion at
append time would be prohbitively expensive.
@pchlupacek
Copy link
Contributor

@mpilquist how is the performance on ++ here ? Last time I did this it was significantly decreasing...

@mpilquist
Copy link
Member Author

In a microbenchmark, we'll certainly see the impact. In real streams, I doubt we'd see an impact though b/c performance we lose from having scopes introduced by ++ we gain from having pulls not introduce scopes, and dominators in real streams will be much different than ++ microbenchmarks. Here are the results of StreamPerformanceSpec before and after the change:
Before:

[info] StreamPerformanceSpec:
[info] Stream Performance
[info]   left-associated ++
[info]   - 2 (316 milliseconds)
[info]   - 3 (2 milliseconds)
[info]   - 100 (4 milliseconds)
[info]   - 200 (6 milliseconds)
[info]   - 400 (9 milliseconds)
[info]   - 800 (12 milliseconds)
[info]   - 1600 (11 milliseconds)
[info]   - 3200 (12 milliseconds)
[info]   - 6400 (16 milliseconds)
[info]   - 12800 (15 milliseconds)
[info]   - 25600 (23 milliseconds)
[info]   - 51200 (23 milliseconds)
[info]   - 102400 (43 milliseconds)
[info]   right-associated ++
[info]   - 2 (2 milliseconds)
[info]   - 3 (0 milliseconds)
[info]   - 100 (1 millisecond)
[info]   - 200 (1 millisecond)
[info]   - 400 (2 milliseconds)
[info]   - 800 (2 milliseconds)
[info]   - 1600 (3 milliseconds)
[info]   - 3200 (6 milliseconds)
[info]   - 6400 (4 milliseconds)
[info]   - 12800 (7 milliseconds)
[info]   - 25600 (9 milliseconds)
[info]   - 51200 (16 milliseconds)
[info]   - 102400 (41 milliseconds)
[info]   left-associated flatMap 1
[info]   - 2 (7 milliseconds)
[info]   - 3 (3 milliseconds)
[info]   - 100 (1 millisecond)
[info]   - 200 (3 milliseconds)
[info]   - 400 (4 milliseconds)
[info]   - 800 (6 milliseconds)
[info]   - 1600 (4 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (5 milliseconds)
[info]   - 12800 (19 milliseconds)
[info]   - 25600 (22 milliseconds)
[info]   - 51200 (39 milliseconds)
[info]   - 102400 (35 milliseconds)
[info]   left-associated eval() ++ flatMap 1
[info]   - 2 (4 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (2 milliseconds)
[info]   - 200 (3 milliseconds)
[info]   - 400 (5 milliseconds)
[info]   - 800 (5 milliseconds)
[info]   - 1600 (3 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (8 milliseconds)
[info]   - 12800 (10 milliseconds)
[info]   - 25600 (18 milliseconds)
[info]   - 51200 (56 milliseconds)
[info]   - 102400 (101 milliseconds)
[info]   right-associated flatMap 1
[info]   - 2 (1 millisecond)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (1 millisecond)
[info]   - 400 (2 milliseconds)
[info]   - 800 (2 milliseconds)
[info]   - 1600 (2 milliseconds)
[info]   - 3200 (7 milliseconds)
[info]   - 6400 (11 milliseconds)
[info]   - 12800 (12 milliseconds)
[info]   - 25600 (26 milliseconds)
[info]   - 51200 (32 milliseconds)
[info]   - 102400 (28 milliseconds)
[info]   right-associated eval() ++ flatMap 1
[info]   - 2 (2 milliseconds)
[info]   - 3 (0 milliseconds)
[info]   - 100 (0 milliseconds)
[info]   - 200 (1 millisecond)
[info]   - 400 (2 milliseconds)
[info]   - 800 (2 milliseconds)
[info]   - 1600 (2 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (8 milliseconds)
[info]   - 12800 (7 milliseconds)
[info]   - 25600 (16 milliseconds)
[info]   - 51200 (65 milliseconds)
[info]   - 102400 (57 milliseconds)
[info]   left-associated flatMap 2
[info]   - 2 (9 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (8 milliseconds)
[info]   - 200 (9 milliseconds)
[info]   - 400 (13 milliseconds)
[info]   - 800 (10 milliseconds)
[info]   - 1600 (15 milliseconds)
[info]   - 3200 (23 milliseconds)
[info]   - 6400 (26 milliseconds)
[info]   - 12800 (32 milliseconds)
[info]   - 25600 (125 milliseconds)
[info]   - 51200 (162 milliseconds)
[info]   - 102400 (265 milliseconds)
[info]   right-associated flatMap 2
[info]   - 2 (2 milliseconds)
[info]   - 3 (0 milliseconds)
[info]   - 100 (0 milliseconds)
[info]   - 200 (0 milliseconds)
[info]   - 400 (1 millisecond)
[info]   - 800 (0 milliseconds)
[info]   - 1600 (1 millisecond)
[info]   - 3200 (2 milliseconds)
[info]   - 6400 (3 milliseconds)
[info]   - 12800 (3 milliseconds)
[info]   - 25600 (7 milliseconds)
[info]   - 51200 (13 milliseconds)
[info]   - 102400 (28 milliseconds)
[info]   transduce (id)
[info]   - 2 (16 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (6 milliseconds)
[info]   - 200 (9 milliseconds)
[info]   - 400 (13 milliseconds)
[info]   - 800 (9 milliseconds)
[info]   - 1600 (15 milliseconds)
[info]   - 3200 (14 milliseconds)
[info]   - 6400 (22 milliseconds)
[info]   - 12800 (26 milliseconds)
[info]   - 25600 (22 milliseconds)
[info]   - 51200 (157 milliseconds)
[info]   - 102400 (121 milliseconds)
[info]   bracket + handleErrorWith (1)
[info]   - 2 (19 milliseconds)
[info]   - 3 (2 milliseconds)
[info]   - 100 (27 milliseconds)
[info]   - 200 (26 milliseconds)
[info]   - 400 (37 milliseconds)
[info]   - 800 (30 milliseconds)
[info]   - 1600 (32 milliseconds)
[info]   - 3200 (42 milliseconds)
[info]   - 6400 (51 milliseconds)
[info]   - 12800 (84 milliseconds)
[info]   - 25600 (154 milliseconds)
[info]   - 51200 (596 milliseconds)
[info]   - 102400 (753 milliseconds)
[info]   chunky flatMap
[info]   - 2 (4 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (2 milliseconds)
[info]   - 400 (3 milliseconds)
[info]   - 800 (3 milliseconds)
[info]   - 1600 (5 milliseconds)
[info]   - 3200 (10 milliseconds)
[info]   - 6400 (19 milliseconds)

After:

[info] StreamPerformanceSpec:
[info] Stream Performance
[info]   left-associated ++
[info]   - 2 (341 milliseconds)
[info]   - 3 (2 milliseconds)
[info]   - 100 (13 milliseconds)
[info]   - 200 (21 milliseconds)
[info]   - 400 (31 milliseconds)
[info]   - 800 (30 milliseconds)
[info]   - 1600 (25 milliseconds)
[info]   - 3200 (36 milliseconds)
[info]   - 6400 (52 milliseconds)
[info]   - 12800 (44 milliseconds)
[info]   - 25600 (63 milliseconds)
[info]   - 51200 (113 milliseconds)
[info]   - 102400 (254 milliseconds)
[info]   right-associated ++
[info]   - 2 (2 milliseconds)
[info]   - 3 (0 milliseconds)
[info]   - 100 (2 milliseconds)
[info]   - 200 (2 milliseconds)
[info]   - 400 (2 milliseconds)
[info]   - 800 (3 milliseconds)
[info]   - 1600 (4 milliseconds)
[info]   - 3200 (6 milliseconds)
[info]   - 6400 (8 milliseconds)
[info]   - 12800 (53 milliseconds)
[info]   - 25600 (121 milliseconds)
[info]   - 51200 (63 milliseconds)
[info]   - 102400 (172 milliseconds)
[info]   left-associated flatMap 1
[info]   - 2 (5 milliseconds)
[info]   - 3 (3 milliseconds)
[info]   - 100 (1 millisecond)
[info]   - 200 (3 milliseconds)
[info]   - 400 (4 milliseconds)
[info]   - 800 (5 milliseconds)
[info]   - 1600 (4 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (5 milliseconds)
[info]   - 12800 (15 milliseconds)
[info]   - 25600 (12 milliseconds)
[info]   - 51200 (20 milliseconds)
[info]   - 102400 (62 milliseconds)
[info]   left-associated eval() ++ flatMap 1
[info]   - 2 (4 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (2 milliseconds)
[info]   - 200 (4 milliseconds)
[info]   - 400 (4 milliseconds)
[info]   - 800 (4 milliseconds)
[info]   - 1600 (6 milliseconds)
[info]   - 3200 (10 milliseconds)
[info]   - 6400 (13 milliseconds)
[info]   - 12800 (22 milliseconds)
[info]   - 25600 (56 milliseconds)
[info]   - 51200 (27 milliseconds)
[info]   - 102400 (51 milliseconds)
[info]   right-associated flatMap 1
[info]   - 2 (1 millisecond)
[info]   - 3 (0 milliseconds)
[info]   - 100 (0 milliseconds)
[info]   - 200 (1 millisecond)
[info]   - 400 (2 milliseconds)
[info]   - 800 (2 milliseconds)
[info]   - 1600 (3 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (5 milliseconds)
[info]   - 12800 (5 milliseconds)
[info]   - 25600 (9 milliseconds)
[info]   - 51200 (14 milliseconds)
[info]   - 102400 (23 milliseconds)
[info]   right-associated eval() ++ flatMap 1
[info]   - 2 (3 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (2 milliseconds)
[info]   - 400 (2 milliseconds)
[info]   - 800 (1 millisecond)
[info]   - 1600 (1 millisecond)
[info]   - 3200 (3 milliseconds)
[info]   - 6400 (5 milliseconds)
[info]   - 12800 (8 milliseconds)
[info]   - 25600 (27 milliseconds)
[info]   - 51200 (27 milliseconds)
[info]   - 102400 (56 milliseconds)
[info]   left-associated flatMap 2
[info]   - 2 (9 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (9 milliseconds)
[info]   - 200 (9 milliseconds)
[info]   - 400 (11 milliseconds)
[info]   - 800 (13 milliseconds)
[info]   - 1600 (24 milliseconds)
[info]   - 3200 (29 milliseconds)
[info]   - 6400 (38 milliseconds)
[info]   - 12800 (83 milliseconds)
[info]   - 25600 (270 milliseconds)
[info]   - 51200 (214 milliseconds)
[info]   - 102400 (844 milliseconds)
[info]   right-associated flatMap 2
[info]   - 2 (2 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (0 milliseconds)
[info]   - 400 (1 millisecond)
[info]   - 800 (1 millisecond)
[info]   - 1600 (1 millisecond)
[info]   - 3200 (3 milliseconds)
[info]   - 6400 (6 milliseconds)
[info]   - 12800 (7 milliseconds)
[info]   - 25600 (21 milliseconds)
[info]   - 51200 (43 milliseconds)
[info]   - 102400 (75 milliseconds)
[info]   transduce (id)
[info]   - 2 (21 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (5 milliseconds)
[info]   - 200 (9 milliseconds)
[info]   - 400 (12 milliseconds)
[info]   - 800 (15 milliseconds)
[info]   - 1600 (21 milliseconds)
[info]   - 3200 (35 milliseconds)
[info]   - 6400 (47 milliseconds)
[info]   - 12800 (80 milliseconds)
[info]   - 25600 (116 milliseconds)
[info]   - 51200 (109 milliseconds)
[info]   - 102400 (220 milliseconds)
[info]   bracket + handleErrorWith (1)
[info]   - 2 (73 milliseconds)
[info]   - 3 (3 milliseconds)
[info]   - 100 (30 milliseconds)
[info]   - 200 (31 milliseconds)
[info]   - 400 (41 milliseconds)
[info]   - 800 (33 milliseconds)
[info]   - 1600 (44 milliseconds)
[info]   - 3200 (64 milliseconds)
[info]   - 6400 (86 milliseconds)
[info]   - 12800 (162 milliseconds)
[info]   - 25600 (352 milliseconds)
[info]   - 51200 (741 milliseconds)
[info]   - 102400 (1 second, 480 milliseconds)
[info]   chunky flatMap
[info]   - 2 (3 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (2 milliseconds)
[info]   - 400 (3 milliseconds)
[info]   - 800 (4 milliseconds)
[info]   - 1600 (4 milliseconds)
[info]   - 3200 (8 milliseconds)
[info]   - 6400 (20 milliseconds)

@mpilquist
Copy link
Member Author

Another option would be leaving ++ as not introducing a scope and instead, rely on manual introduction of scopes along with a few special cases like repeat and handleErrorWith. I think I might like this solution the best. What do you think?

@pchlupacek
Copy link
Contributor

@mpilquist when we exactly need to introduce the scope? I was not clear on purpose of having it in repeatEval, but

  • repeatEval is used imho more often than ++ in any program, for sure given how map is defined, so I would say this is anyhow move in right direction
  • To answer your question, I would really need to understand why scope was there (in Pull) at all. Remember we have it now with handleErrorWith, so perhaps now, we can catch the exceptions correctly (I am thinking this may have been the issue earlier?)

@pchlupacek
Copy link
Contributor

As a side note, with new interruption in algebra, we may also introduce more correct error propagation around scopes, essentially eliminating out-of-scope shortcuts, if necessary. This is almost zero cost, so if the scopes was introduced for that reason, I am quite sure we can remove them alltogether.

@mpilquist
Copy link
Member Author

@pchlupacek I agree, we don't need automatic scoping around repeat. I've updated this branch such that the only automatic scoping is in handleErrorWith. All tests pass without modifications. I think this is the right set of tradeoffs -- both ++ and the Pull API are now fast and handleErrorWith has the expected behavior.

@mpilquist
Copy link
Member Author

Performance as of aa50586:

[info] Stream Performance
[info]   left-associated ++
[info]   - 2 (368 milliseconds)
[info]   - 3 (2 milliseconds)
[info]   - 100 (6 milliseconds)
[info]   - 200 (8 milliseconds)
[info]   - 400 (15 milliseconds)
[info]   - 800 (21 milliseconds)
[info]   - 1600 (17 milliseconds)
[info]   - 3200 (16 milliseconds)
[info]   - 6400 (23 milliseconds)
[info]   - 12800 (23 milliseconds)
[info]   - 25600 (29 milliseconds)
[info]   - 51200 (25 milliseconds)
[info]   - 102400 (50 milliseconds)
[info]   right-associated ++
[info]   - 2 (2 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (1 millisecond)
[info]   - 400 (2 milliseconds)
[info]   - 800 (3 milliseconds)
[info]   - 1600 (5 milliseconds)
[info]   - 3200 (3 milliseconds)
[info]   - 6400 (5 milliseconds)
[info]   - 12800 (7 milliseconds)
[info]   - 25600 (9 milliseconds)
[info]   - 51200 (19 milliseconds)
[info]   - 102400 (41 milliseconds)
[info]   left-associated flatMap 1
[info]   - 2 (14 milliseconds)
[info]   - 3 (3 milliseconds)
[info]   - 100 (3 milliseconds)
[info]   - 200 (4 milliseconds)
[info]   - 400 (5 milliseconds)
[info]   - 800 (5 milliseconds)
[info]   - 1600 (5 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (9 milliseconds)
[info]   - 12800 (19 milliseconds)
[info]   - 25600 (19 milliseconds)
[info]   - 51200 (41 milliseconds)
[info]   - 102400 (38 milliseconds)
[info]   left-associated eval() ++ flatMap 1
[info]   - 2 (13 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (3 milliseconds)
[info]   - 200 (3 milliseconds)
[info]   - 400 (6 milliseconds)
[info]   - 800 (3 milliseconds)
[info]   - 1600 (2 milliseconds)
[info]   - 3200 (6 milliseconds)
[info]   - 6400 (11 milliseconds)
[info]   - 12800 (9 milliseconds)
[info]   - 25600 (12 milliseconds)
[info]   - 51200 (48 milliseconds)
[info]   - 102400 (102 milliseconds)
[info]   right-associated flatMap 1
[info]   - 2 (2 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (2 milliseconds)
[info]   - 200 (1 millisecond)
[info]   - 400 (4 milliseconds)
[info]   - 800 (3 milliseconds)
[info]   - 1600 (2 milliseconds)
[info]   - 3200 (4 milliseconds)
[info]   - 6400 (8 milliseconds)
[info]   - 12800 (14 milliseconds)
[info]   - 25600 (24 milliseconds)
[info]   - 51200 (29 milliseconds)
[info]   - 102400 (27 milliseconds)
[info]   right-associated eval() ++ flatMap 1
[info]   - 2 (2 milliseconds)
[info]   - 3 (0 milliseconds)
[info]   - 100 (1 millisecond)
[info]   - 200 (1 millisecond)
[info]   - 400 (2 milliseconds)
[info]   - 800 (1 millisecond)
[info]   - 1600 (2 milliseconds)
[info]   - 3200 (5 milliseconds)
[info]   - 6400 (8 milliseconds)
[info]   - 12800 (8 milliseconds)
[info]   - 25600 (14 milliseconds)
[info]   - 51200 (63 milliseconds)
[info]   - 102400 (57 milliseconds)
[info]   left-associated flatMap 2
[info]   - 2 (7 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (7 milliseconds)
[info]   - 200 (11 milliseconds)
[info]   - 400 (9 milliseconds)
[info]   - 800 (9 milliseconds)
[info]   - 1600 (13 milliseconds)
[info]   - 3200 (18 milliseconds)
[info]   - 6400 (20 milliseconds)
[info]   - 12800 (35 milliseconds)
[info]   - 25600 (140 milliseconds)
[info]   - 51200 (154 milliseconds)
[info]   - 102400 (247 milliseconds)
[info]   right-associated flatMap 2
[info]   - 2 (2 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (1 millisecond)
[info]   - 200 (1 millisecond)
[info]   - 400 (1 millisecond)
[info]   - 800 (0 milliseconds)
[info]   - 1600 (0 milliseconds)
[info]   - 3200 (1 millisecond)
[info]   - 6400 (2 milliseconds)
[info]   - 12800 (3 milliseconds)
[info]   - 25600 (7 milliseconds)
[info]   - 51200 (13 milliseconds)
[info]   - 102400 (22 milliseconds)
[info]   transduce (id)
[info]   - 2 (16 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (6 milliseconds)
[info]   - 200 (9 milliseconds)
[info]   - 400 (8 milliseconds)
[info]   - 800 (11 milliseconds)
[info]   - 1600 (16 milliseconds)
[info]   - 3200 (16 milliseconds)
[info]   - 6400 (25 milliseconds)
[info]   - 12800 (29 milliseconds)
[info]   - 25600 (49 milliseconds)
[info]   - 51200 (223 milliseconds)
[info]   - 102400 (125 milliseconds)
[info]   bracket + handleErrorWith (1)
[info]   - 2 (36 milliseconds)
[info]   - 3 (3 milliseconds)
[info]   - 100 (24 milliseconds)
[info]   - 200 (27 milliseconds)
[info]   - 400 (32 milliseconds)
[info]   - 800 (29 milliseconds)
[info]   - 1600 (36 milliseconds)
[info]   - 3200 (45 milliseconds)
[info]   - 6400 (54 milliseconds)
[info]   - 12800 (86 milliseconds)
[info]   - 25600 (149 milliseconds)
[info]   - 51200 (568 milliseconds)
[info]   - 102400 (910 milliseconds)
[info]   chunky flatMap
[info]   - 2 (3 milliseconds)
[info]   - 3 (1 millisecond)
[info]   - 100 (2 milliseconds)
[info]   - 200 (2 milliseconds)
[info]   - 400 (2 milliseconds)
[info]   - 800 (4 milliseconds)
[info]   - 1600 (6 milliseconds)
[info]   - 3200 (10 milliseconds)
[info]   - 6400 (17 milliseconds)

@pchlupacek
Copy link
Contributor

@mpilquist excellent :-)

@mpilquist
Copy link
Member Author

@pchlupacek OK to merge then?

@SystemFw
Copy link
Collaborator

SystemFw commented Jan 8, 2018

and instead, rely on manual introduction of scopes

I'm a bit unclear on the extent of the implications of this for end users

@mpilquist
Copy link
Member Author

@SystemFw I don't think there are any really now that handleErrorWith introduces a scope and interruption has been fixed.

@SystemFw
Copy link
Collaborator

SystemFw commented Jan 8, 2018

Right, that's what I was hoping to hear, but the original phrasing confused me a bit :)
👍 👍

@mpilquist
Copy link
Member Author

OK merging. That leaves just #1061 and then we can release a 0.10.0-RC1.

@mpilquist mpilquist merged commit 47e41db into typelevel:series/0.10 Jan 8, 2018
@mpilquist mpilquist deleted the topic/pure-no-scope branch February 18, 2020 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants