lasselukkari / aWOT

Arduino web server library.
MIT License
283 stars 41 forks source link

Allow using user defined buffers #125

Closed lasselukkari closed 3 years ago

EmperorArthur commented 3 years ago

So, there's an interesting part of this that I think is worth looking at. The previous method had the disadvantage of re-using objects. However, it had the advantage of almost completely static RAM usage. Honestly, I prefer this new method, but just wanted to point it out for anyone who sees the library memory consumption go down.

To anyone who sees your RAM usage massively decrease after this change: READ THIS

Application::process takes the same amount of RAM it always has. Application just doesn't use the RAM until process(client) is called! This isn't some magic RAM reduction update. It merely delays it until later.

Alternately, you can use the new feature and define your own buffer. There's still some allocation overhead as the Request and Response objects are now created on the fly, but if you're after an HTTP library with zero dynamic allocation, you're in a very niche market.

lasselukkari commented 3 years ago

I agree with you about this completely and I made the decision to change this carefully. I made the same decision the other way around many years ago. I will be writing a documentation page about the memory usage and how the user can affect and optimise it before I release the next version.

lasselukkari commented 3 years ago

What could be done is to add yet another process method version where the request and response objects would be given as parameters. The constructor of Request and Response are currently private but making them public could allow better unit testing for middleware functions in end user apps too.

EmperorArthur commented 3 years ago

Possibly, though the overhead is small enough that I wouldn't consider it worth it at first glance. After all, we're talking less than 100 bytes if the buffers are pre-allocated.

Unfortunately, memory constraints, the lack of exceptions, and not having std::move make it hard for this library to behave like some higher level frameworks. For example Django (Python3) works like this.

First, the request is routed thrugh all the seperate middleware. The Middleware may only modify system state and the request itself. Then, the function that the request is routed to constructs and returns an HTTPResponse object that is sent to the client. Finally, anywhere in that chain certain exceptions are also treated as HTTPResponses. Which is how 401/403 work.

So, given that constraint, the current Middleware approach works pretty good!

lasselukkari commented 3 years ago

Outside my hobby MCU projects I have been using Go for most server side things during the past few years. Maybe because of that I have started to appreciate explicit coding style a lot more. For me not having exceptions is not really a problem and I kinda actually prefer it this way.

BTW I have been lately running some tests on my pc comparing the performance of aWOT with simple unix socket Client wrappers to many popular frameworks. It seems to perform rather well and the memory footprint is really small compared to most. One of the reasons for this change was to be able to process those sockets with in multiple threads.