c-cube / tiny_httpd

Minimal HTTP server using good old threads + blocking IO, with a small request router.
https://c-cube.github.io/tiny_httpd
75 stars 11 forks source link

Domains #48

Closed craff closed 1 year ago

craff commented 1 year ago

A very small optional library to provide a run and new_thread allowing to use OCaml 5 domains.

Before merging, we need to do

I want to add a file cache for static file, which requires to use OCaml 5 to make it simple.

craff commented 1 year ago

Compilation should now work for ocaml 4

craff commented 1 year ago

It compiles (dune build works) but opam is not happy and .expect should depend also on ocaml_version

craff commented 1 year ago

I am progressing on tests but some tests like sse_count can now be out of order (why could not they be bofore ?). I will test you when both dune build and dune test works. For opam, I am not sur yet how to handle tiny_httpd_domains that require ocaml-5?

craff commented 1 year ago

It now works and ignore tiny_httpd_domains on ocaml 4. However, I failed to adapt the .yml.

craff commented 1 year ago

I understand what we really need. My code is only working in max_connection = number of domains. Eio is the solution, but this requires rewrite tiny_httpd quite a bit . And Cohttp_eio is already there. I don't know if this is worth it.

c-cube commented 1 year ago

indeed, with multicore you probably want to use effects to get much more lightweight IOs, which means Eio.

craff commented 1 year ago

Hello,

Simon Cruanes writes:

indeed, with multicore you probably want to use effects to get much more lightweight IOs, which means Eio.

Yes, I tried, but some goodies included in tiny_httpd are not there, like camlzip. However, with cohttp-eio I could use a cache for compressed zlib file and immediatly got a 2x boost in performance. Moreover, I could use a pool of data base connection for each domain. All this is very nice and should allow reaching state of the art performance.

Still, I find Tiny_httpd better, because more compact. with cohttpd_eio, you also have to use http and uri. Finding the correct functions to compose is long and cumbersome.

We could write a minimalist module with Effect (I almost started to do this yesterday) dedicated to just what we need. This would give a Tiny_httpd that would only depends on Domain and Effect (no dependency one Eio, domainslib, Cohttp, etc).

There is only the question of using Unix.select or something more efficient when available as Eio is doing. This could even be more efficient than cohttp_eio because light is often faster.

Would you accept a PR in that direction ?

Cheers, Christophe

-- Christophe Raffalli tél: +689 87 23 11 48 web: http://raffalli.eu

c-cube commented 1 year ago

I think it'd be interesting to start a different project named tiny_httpd_eio or something, with a full port to Eio. A few major changes are required to make it good for Eio, and that comprises:

That's a lot of changes for tiny_httpd, and it'd 100% break it for OCaml 4.x, so I think it'd be better to make a fork into a separate library instead if that's what you want.

-- Simon Cruanes

craff commented 1 year ago

Yes I think it would be a fork of Tiny_httpd.

However, I am not sure we need Eio. The structure we have for a web server for domains/fiber is very rigid: all domains are doing exactly the same thing, and we only need a non blocking select/read/write and maybe a yield for request that need time to be handled (even if a good design would split them is smaller request). We know that write by the server will probably not block (client are usually available) so we can use that in the design.

I don't think it is a lot of code to have this, and it would probably be a little faster, and would not require to follow the evolution of Eio which is very young?

c-cube commented 1 year ago

However, I am not sure we need Eio. The structure we have for a web server for domains/fiber is very rigid: all domains are doing exactly the same thing, and we only need a non blocking select/read/write and maybe a yield for request that need time to be handled (even if a good design would split them is smaller request).

Having a yield and non blocking IOs means you need a scheduler. Then you also probably want some sort of stream (which Eio does provide). And an abstraction over how to do these IOs on various platforms: epoll, kqueue, io_uring, etc.

My point is: for non blocking stuff, I think that not using Eio is a bit of a waste of time. It's also a loss of interoperability with other OCaml 5 libraries, because they won't have compatible effects for fibers and the likes.

We know that write by the server will probably not block (client are usually available) so we can use that in the design.

I don't think it is a lot of code to have this, and it would probably be a little faster, and would not require to follow the evolution of Eio which is very young?

Faster than Eio, I doubt that :-). Remember that we'd have to write our own scheduler…

craff commented 1 year ago

Simon Cruanes writes:

However, I am not sure we need Eio. The structure we have for a web server for domains/fiber is very rigid: all domains are doing exactly the same thing, and we only need a non blocking select/read/write and maybe a yield for request that need time to be handled (even if a good design would split them is smaller request).

Having a yield and non blocking IOs means you need a scheduler. Then you also probably want some sort of stream (which Eio does provide).

Yes, a simple O(1) scheduler per domain + possibility to change domain between request if domain is overloaded:

And an abstraction over how to do these IOs on various platforms: epoll, kqueue, io_uring, etc.

We can do POSIX IO only first.

My point is: for non blocking stuff, I think that not using Eio is a bit of a waste of time. It's also a loss of interoperability with other OCaml 5 libraries, because they won't have compatible effects for fibers and the likes.

Don't think this is a problem for Tiny_httpd. At least not for me. As long as a user does not need domains, there should be no problem.

I intend to provide shared data per session, but across domains. This is needed because one session may have more than one connection. This should allow for most application.

Faster than Eio, I doubt that :-). Remember that we'd have to write our own scheduler…

Simpler and specialized is almost always faster.

I will work on a fork named tiny_httpd_domains and invite you when it starts working.

If it fails I will try eio;-)

Cheers, Christophe

-- Christophe Raffalli tél: +689 87 23 11 48 web: http://raffalli.eu