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

Switch from network to socket #306

Closed
wants to merge 4 commits into from
Closed

Conversation

tfausak
Copy link
Contributor

@tfausak tfausak commented Oct 26, 2017

This pull request explores switching from the venerable network package to @lpeterse's socket package. The switch turned out to be easier than I expected. Nevertheless, a few of the tests fail:

  test-nonet/Network/HTTP/ClientSpec.hs:188: 
  1) Network.HTTP.Client.Client early close on a 413
       uncaught exception: SocketException (ePipe)

  test-nonet/Network/HTTP/ClientSpec.hs:194: 
  2) Network.HTTP.Client.Client length zero and chunking zero #108
       uncaught exception: SocketException (ePipe)

  test-nonet/Network/HTTP/ClientSpec.hs:199: 
  3) Network.HTTP.Client.Client length zero and chunking
       uncaught exception: SocketException (ePipe)

  test-nonet/Network/HTTP/ClientSpec.hs:204: 
  4) Network.HTTP.Client.Client length and chunking
       uncaught exception: SocketException (eProtocolType)

I didn't spend much time trying to debug those because they seem to rely on streaming-commons, which itself depends on network and exposes Sockets.

My goal here isn't actually to replace network with socket — at least not right away. I wanted to see if it was possible and how it affected performance (since socket uses MVars behind the scenes). Sadly I don't have an off-the-shelf way to measure the performance of http-client. I'll have to look around for one unless someone has a better idea. I tried running http-client/bench/threaded-stress.hs, but after bringing it up to date I realized it doesn't really stress test the sockets.

cc @eborden @snoyberg

@tfausak
Copy link
Contributor Author

tfausak commented Oct 26, 2017

I wrote a little benchmark to make a bunch of requests on a single thread as fast as possible: https://gist.github.com/tfausak/afab233786cee3090f55974ffe0b1ba8/062b0a042b971c7c1f5f0341d4fc08d9e842535a

The initial results are very good! So good, in fact, that I feel like I must have done something wrong.

  • Performing 1,000 requests and creating a new manager for each request:
    • network (a47c484): 174 requests per second
    • socket (b9cf36e): 1,607 requests per second
  • Performing 1,000 requests and using the same manager for every request:
    • network: 177 requests per second
    • socket: 1750 requests per second

Is it possible that socket is an order of magnitude faster than network? That seems crazy.

I also saw some crashes (ConnectionTimeout) when increasing the number of requests with network. They don't consistently happen, but I did see them. I didn't see any crashes with socket.

@lpeterse
Copy link

@tfausak Have you used the threaded or non-threaded GHC runtime?

@tfausak
Copy link
Contributor Author

tfausak commented Oct 26, 2017

Alright, I updated my benchmark to be a little more like the real world and a little less synthetic: https://gist.github.com/tfausak/afab233786cee3090f55974ffe0b1ba8/b5e3a58e342b66658ff386529bf6ad895ba92e8b

The order of magnitude difference is gone. Both branches now perform basically the same.

I ran those benchmarks with these ghc-options: -O2 -rtsopts -threaded -Wall -with-rtsopts=-N. None of the options seem to have any noticeable impact on performance. For example, I see >9,000 RPS even with just ghc-options: -Wall.

@eborden
Copy link

eborden commented Oct 26, 2017

This change set is surprisingly small. I'll take a closer look at this later. Looks pretty nice at a glance.

@eborden
Copy link

eborden commented Oct 26, 2017

I'd love to see some profiling and threadscope displays of these benchmarks. I'm really curious if the performance gains are coming from less allocation via socket's newtype and typeclass dispatched representation.

@eborden
Copy link

eborden commented Oct 26, 2017

The other interesting thing to test would be a benchmark that generates high contention between writing threads. That is an area where the MVar might produce a bottleneck.

@eborden
Copy link

eborden commented Oct 26, 2017

Pulling in @kazu-yamamoto for curiosity.

@tfausak
Copy link
Contributor Author

tfausak commented Oct 27, 2017

I'm not familiar with thread scope, but I can do some profiled runs.

Any ideas for how to create a workload that would have a lot of contention? My naive guess is to basically do the same thing as my linear benchmark except make the requests on N threads.

@tfausak
Copy link
Contributor Author

tfausak commented Oct 27, 2017

I went ahead and added the benchmark to this branch. I also updated it to use more threads. Then I ran it against master and this branch — they're still really close. network has a slight speed advantage over socket when multiple threads are involved, something like 5% faster.

I also ran the benchmarks with profiling enabled. network and socket are remarkably similar in terms of allocations.

Assuming I did all this correctly (which is a big assumption), network and socket are neck-and-neck.

@eborden
Copy link

eborden commented Oct 27, 2017

Veeeerrrrry interesting. We avoided adding an MVar to network in recent history because we feared the performance implications. This is some great information and experimentation 💯

@eborden
Copy link

eborden commented Oct 27, 2017

I'm very tempted to produce a major epoch in network that steals all the good ideas in socket, while maintaining networks greater support for POSIX modifications and bespoke apis.

But before I think about that I'll have to don my powdered wig.
image

@kazu-yamamoto
Copy link
Contributor

@eborden You should open an issue on the network package.

@tfausak
Copy link
Contributor Author

tfausak commented Dec 20, 2017

How is the powdered wiggery going?

@eborden
Copy link

eborden commented Dec 20, 2017

@tfausak https://github.com/haskell/network/projects

@eborden
Copy link

eborden commented Dec 20, 2017

Granted 3.0.0.0 is purely theory and intended as a pie in the sky project.

@eborden eborden mentioned this pull request Dec 28, 2017
@tfausak
Copy link
Contributor Author

tfausak commented Feb 1, 2018

I'm going to close this. I never intended for this to be merged. The excellent maintainers of network have already made big strides toward incorporating socket's ideas into version 3. 🎉 haskell/network#295

@tfausak tfausak closed this Feb 1, 2018
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.

4 participants