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

Conversion of MessageBody to accept Pin in poll_next #1332

Merged
merged 32 commits into from
Feb 17, 2020

Conversation

dunnock
Copy link
Contributor

@dunnock dunnock commented Jan 29, 2020

Starting conversion of MessageBody to accept poll_next(self: Pin<&mut Self...) as it was adviced in #1321 (comment) .

This is breaking change and probably should be included in the next version, amended versions accordingly.

Following versions updated as part of this PR to align with semver:

actix-http 1 -> 2.0.0-alpha

Checklist:

  • Draft implementation of actix-http
  • Fix tests in actix-http
  • Benchmark & compare with non Pin version
  • Prereview
  • Review

Move to another PR / tasks

  • Publish actix-http with version 2.0.0-alpha to crates
  • Fix dependencies (actix-web and awc), update versions:
    actix-web 2.0 -> 2.1 (probably should go to 3.0?)
    awc 1 -> 2

@JohnTitor
Copy link
Member

Could you reword b55aa2e? Otherwise it'll close mentioned issue.

- Convert MessageBody to accept Pin in poll_next

- add CHANGES and increase versions aligned to semver

- update crates to accomodate MessageBody Pin change

- fix tests and dependencies
@dunnock
Copy link
Contributor Author

dunnock commented Jan 30, 2020

Could you reword b55aa2e? Otherwise it'll close mentioned issue.

Done, had to squash them but it seems no conflicts so ok

@dunnock
Copy link
Contributor Author

dunnock commented Jan 30, 2020

After running benchmarks and separately load testing actix server with ab I do not see any significant difference in performance, pinned version seems working slightly faster but most likely it is just random variance:

ApacheBenchmark

Tests performed on ubuntu with 32GB RAM and 40 CPU

> ab -n 1000000 -c 40 -k ...

Version from this branch using Pin in poll_next():

> ab -n 1000000 -c 40 -k ...
Concurrency Level:      40
Time taken for tests:   29.673 seconds
Complete requests:      1000000
Failed requests:        0
Keep-Alive requests:    1000000
Total transferred:      220000000 bytes
HTML transferred:       119000000 bytes
Requests per second:    33701.00 [#/sec] (mean)
Time per request:       1.187 [ms] (mean)
Time per request:       0.030 [ms] (mean, across all concurrent requests)
Transfer rate:          7240.45 [Kbytes/sec] received

Version from master branch:

Concurrency Level:      40
Time taken for tests:   30.945 seconds
Complete requests:      1000000
Failed requests:        0
Keep-Alive requests:    1000000
Total transferred:      220000000 bytes
HTML transferred:       119000000 bytes
Requests per second:    32315.58 [#/sec] (mean)
Time per request:       1.238 [ms] (mean)
Time per request:       0.031 [ms] (mean, across all concurrent requests)
Transfer rate:          6942.80 [Kbytes/sec] received

cargo bench

Version with Pin:

get_body_async_burst    time:   [118.97 us 120.46 us 121.87 us]

Version from Master:

get_body_async_burst    time:   [121.38 us 122.17 us 122.90 us]

@dunnock dunnock marked this pull request as ready for review January 30, 2020 15:54
@JohnTitor
Copy link
Member

Rough reviews at this point:

  • Do not update actix-{identify, session} here, we're moving out from here now, see https://github.com/actix/actix-extras.
  • I'm negative to update all workspace members at once, we should do step by step as possible.
  • The version numbers should be alpha since we may add breaking changes later. And I'm also negative to bump them here.

At a glance, the benchmark you commented looks good to me, so the change should be fine roughly.

@dunnock
Copy link
Contributor Author

dunnock commented Jan 30, 2020

@JohnTitor need your advice. I initially wanted to include only changes in actix-http and point rest of crates to version 1.0.1. Though it appeared problematic as there is dependency chain:
actix-http dev dependency is actix-http-test { ./test-server } which depends on awc, actix-web and actix-http
In turn awc depends on actix-http, actix-web and actix-http-test
actix-web depends on actix-http too

To illustrate the issue I have just pushed commit pointing actix-http to actix-http-test:1.0.0:

Problem is actix-http-test crate is used only to run some tests within actix-http crate, though if I do not provide updated version of awc and actix-web actix-http tests do not compile as they use different versions of structs and traits : actix-http:1.0.1 and actix-http:2.0.0.

Once I update actix-web, crates actix-{identify, session} fail to compile.

One possible solution is to move out actix-http tests which depend on actix-http-test crate. Another option would be to comment out those tests temporarily.

@JohnTitor
Copy link
Member

One safe way is to prepare another branch and work there. You can ignore workspace members that don't compile there. I just prepared msg-body branch.
And we can ignore actix-{identity, session} once the alpha version is released and they're published on extras repo.

@dunnock dunnock changed the base branch from master to msg-body January 31, 2020 08:04
@dunnock
Copy link
Contributor Author

dunnock commented Jan 31, 2020

This is ready for review now with all 3 changes as requested.
I believe CI issues not related to this change.

@robjtede robjtede requested a review from a team January 31, 2020 13:45
Cargo.toml Outdated Show resolved Hide resolved
Copy link
Member

@cdbattags cdbattags left a comment

Choose a reason for hiding this comment

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

Small things but otherwise looks great

actix-http/src/encoding/encoder.rs Show resolved Hide resolved
actix-http/src/h1/dispatcher.rs Outdated Show resolved Hide resolved
@dunnock dunnock changed the title WIP: conversion of MessageBody to accept Pin in poll_next Conversion of MessageBody to accept Pin in poll_next Feb 1, 2020
Copy link
Member

@robjtede robjtede left a comment

Choose a reason for hiding this comment

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

Been thinkng about this for a couple days. It seems uneccesary to have MessageBody take the Unpin supertrait. You're handling the self Pin signatures correctly in most places anyway but it'll only takes a couple of modifications to make it work without the supertrait.

Eg. the Box and Box impls can use map_unchecked_mut calls. The h1 dispatcher maybe slightly more involved (just from changing a couple things) but given the h2 dispatcher is already using pin_project it seems achievable.

@dunnock
Copy link
Contributor Author

dunnock commented Feb 3, 2020

@robjtede I have unlinked MessageBody from Unpin as you suggested. h1::dispatcher appeared quite complicated and requires strong review. DispatcherState and SendResponse required some unsafe code too.

@Aaron1011
Copy link
Contributor

Aaron1011 commented Feb 8, 2020

@dunnock: I'm working on changes to pin-project that will help with the line that you mentioned. I can open a PR to address it once this is merged.

@dunnock
Copy link
Contributor Author

dunnock commented Feb 9, 2020

@Aaron1011: If you mean taiki-e/pin-project#181 not sure how that will help here? FramedParts takes ownership of a stream, hence we are taking the Dispatcher::inner value but it is a Pin.

@Aaron1011
Copy link
Contributor

@dunnock: This is different - this idea is to have a pinned_replace method that will allow you to call mem::replace on a pinned enum, if the enum is currently set to a variant that has no #[pin] annotations.

I haven't yet opened a PR for it, but I will soon.

@dunnock
Copy link
Contributor Author

dunnock commented Feb 9, 2020

@Aaron1011 in our case current enum variant is Pinned (DispatcherState::Normal), though we can confidently say that it's Pin not going to be called or accessed from anywhere as previous projections lifetime has ended on a line before.

@dunnock
Copy link
Contributor Author

dunnock commented Feb 10, 2020

Last commits getting rid of unsafe code in a dispatcher with Aaron's idea to transfer not pinned fields (DispatchInner::io, *_buf, codec). Note that unwrap() should behave like a previous implementation which had explicit panic! under same unreachable conditions. @cetra3 @robjtede I guess it now addresses both concerns and can be reviewed again.

Compared to current master this PR removes 4 unsafe blocks from dispatcher not adding any new.

By benchmark it is still have no noticeable difference to the version in master:

> ab -c 40 -n 1000000 -k http://127.0.0.1:59993/
Concurrency Level:      40
Time taken for tests:   30.182 seconds
Complete requests:      1000000
Failed requests:        0
Keep-Alive requests:    1000000
Total transferred:      220000000 bytes
HTML transferred:       119000000 bytes
Requests per second:    33132.75 [#/sec] (mean)
Time per request:       1.207 [ms] (mean)
Time per request:       0.030 [ms] (mean, across all concurrent requests)
Transfer rate:          7118.36 [Kbytes/sec] received

@robjtede
Copy link
Member

I'm liking the look of these changes @dunnock, thanks for putting the time in to this. Will give it a proper look over later today and resubmit review.

@robjtede
Copy link
Member

Really good work; the tendrils of that trait ran much deeper than I thought. I'm glad we kept the Unpin only to necessary parts.

@cdbattags
Copy link
Member

@dunnock amazing work on this

thanks for the time

@Dowwie
Copy link
Contributor

Dowwie commented Feb 14, 2020

@JohnTitor do you see any reason not to merge? would rather you took the lead here..

Copy link
Member

@JohnTitor JohnTitor left a comment

Choose a reason for hiding this comment

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

Really great as a first step! I left a comment for a nit point.

actix-http/Cargo.toml Outdated Show resolved Hide resolved
Copy link
Member

@JohnTitor JohnTitor left a comment

Choose a reason for hiding this comment

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

Sorry for the delay! Let's go ahead :)

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.

9 participants