[Libwebsockets] CPU-intensive and I/O-intensive job in LWS

Andy Green 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:

https://libwebsockets.org/git/libwebsockets/tree/lib/misc/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:

https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/ws-server/minimal-ws-server-threadpool

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.

-Andy

> Thanks
> -Xi
> 
> 
> _______________________________________________
> Libwebsockets mailing list
> Libwebsockets at ml.libwebsockets.org
> https://libwebsockets.org/mailman/listinfo/libwebsockets
> 


More information about the Libwebsockets mailing list