babelouest / ulfius

Web Framework to build REST APIs, Webservices or any HTTP endpoint in C language. Can stream large amount of data, integrate JSON data with Jansson, and create websocket services
https://babelouest.github.io/ulfius
GNU Lesser General Public License v2.1
1.07k stars 183 forks source link

[Question] Switching to thread pool later ... #238

Closed ghost closed 1 year ago

ghost commented 1 year ago

I'm an Ulfius n00b, but experienced C coder. I'm looking at Ulfius for a project I'm working on which has the following characteristics:

So the first 2 of these shout threads processing requests, accessing the big shared data-structure read only, one per request, barely any mutex pain. The second two shout "thread pool".

I see from earlier issues that this is possible, but that by default the threading models is one thread created (then destroyed) for each request, I suspect that this will impose too much load for my 100 request/sec requirement, but I could be wrong.

As a n00b, I'd really like to do the initial version of this the simplest way possible, i.e., using the per-request threads, then if that turns out to struggle with lots of requests, then switch to the thread-pool approach. So my question: in this scenario, would there be a lot of work in doing the switch? i.e., is it just switching to the _mhd variant and filling in the relevant extra details, or would one need to rewrite ones callbacks to take advantage of the pool?

babelouest commented 1 year ago

Hello @jjg-dressipi ,

You have an interesting challenge in there.

First, I don't think it's possible to switch from one thread model to another in the same libmicrohttpd connection. During ulfius_start_framework, ulfius calls MHD_start_daemon with the specified parameters. But I don't think it's possible to change those parameters when the daemon is running. I don't know the details, but it would scare me at least...

But, as a workaround, I can see one or two ideas:

That's the first ideas that come to my mind this morning...

ghost commented 1 year ago

Thanks for the reply! But I think my issue is less scary than that. I mean, if when testing this against realistic data with per-request threading and find that it too heavyweight, what's the work involved in switching the code to use thread pools (permanently), rather than some kind of dynamic support for both modes (which I agree, does sound scary :smile:)

babelouest commented 1 year ago

In terms of performance, I believe ulfius itself can handle 100+ connections per second using the default 1 thread per connection configuration.

The bottleneck may be your big data access, but it's worth a try!

ghost commented 1 year ago

The big data access is pretty fast (in memory shared with the thread), but good to know that Ulfius per-request threads can handle that sort of cadence (and that's a maximum value for me, more usually 10-20/s, with occasional bursts to 100/s). Please feel free to close this now (and many thanks).

babelouest commented 1 year ago

Feel free to open a new issue or a conversation if needed!