[Libwebsockets] CPU-intensive and I/O-intensive job in LWS
andy at warmcat.com
Thu Oct 4 08:40:30 CEST 2018
On 04/10/18 14:14, Xi Chen wrote:
> Hi, Andy
> I need help with dealing the following scenarios:
What is the platform, something really weak?
> [Server case - CPU]
> - With mbedtls, the crypto job might be CPU-intensive, which will block
> the LWS thread. This affects the concurrency capability supported by
> LWS, right? Is it by design of LWS?
Lws is nonblocking and singlethreaded, so yes it is by design. You
can't stop the event loop thread by spinning it in your code without
stopping handling of events... this is a characteristic of all event
loops not just lws.
So you have to adapt your design if you won't block the event loop.
> [Server case - I/O]
> - Suppose server receives a POST request and need to save the data on
> flash. I believe the flash write is blocking most likely, and is not
> recommended to run in LWS callbacks. In this case, what is the
> recommended way to deal with flash write in efficient way?
... it depends on your platform resources and situation.
If your platform is not very constrained, there's no good reason to use
mbedtls when OpenSSL has many optimized implementations for common
platforms. OpenSSL is literally 20+x faster for common tls operations
on x86_64. (And OpenSSL maintainers are not high on NIH.)
The write to serial flash situation you describe exists on the lws ESP32
stuff, when you upload the OTA firmware. But because it's a modal
firmware upgrade type situation, it's OK to block other things.
To solve it, you have to move the slow activity to another thread or
process. That could take the form of buffering the data to be written
in RAM and writing it separately (obviously the wisdom of that depends
entirely on device resources...), or starting a thread when you see the
requested task needs it and using rx flow control to modulate accepting
new data against the progress of writing the last lot. But I have not
spent any time on http/2 rx flow control yet so this is only good for h1
as it stands.
In the case the pattern is a client request triggers something that
takes a long time to complete before generating output, if your platform
is strong enough to support pthreads then look at threadpool:
This lets a wsi defer answering on a connection until something it
wanted to execute completed on a thread from a threadpool. The event
loop continues on as soon as the job is queued on the threadpool. And
the job can sync with the original wsi WRITEABLE callback when it is
ready. The advantage is lws absorbs ALL the thread synchronization
stuff, you don't have to use any pthreads in your code.
There's a minimal example for it here:
Gitohashi (the git web interface those links use) runs everything via
threadpool, because stuff like the blame view can be slow to generate.
By using threadpool a slow job doesn't cause any delay for other clients
(until the pool of threads is wholly occupied). And it can be running n
slow jobs on n cores that way, giving a speedup overall.
> Libwebsockets mailing list
> Libwebsockets at ml.libwebsockets.org
More information about the Libwebsockets