CPU load during HTTP response can get sockets stuck #4463
Replies: 1 comment
-
Posted at 2017-05-11 by @gfwilliams Thanks for the example code! I guess if you check When I finally complete the native AT command firmware this should work a lot better since much more of the AT command handling will be done in interrupts, but as I guess you figured, currently the input data processing is handled in the main thread. There's a roughly 512 byte buffer - but if you stall the main thread for long enough that the buffer gets full, data gets lost. I imagine that if you pre-calculated the There is hardware flow control for the ESP8266 on Espruino WiFi, which I haven't turned on because at the moment there isn't a way to use it in Espruino. However, you could still use it manually by doing something like:
(I think - I could have got the polarity of A15 wrong). In your initial code, where you were using the filesystem, did Posted at 2017-05-11 by dave_irvine Aha, I keep forgetting the
Is there any concept of multithreading in Espruino? I'm not even sure if the CPU supports it. Pre-calculated junk works fine, I was just using it as an example of a "busy" Espruino, whether that is CPU or talking to the SD card. I tried setting the SD card baud ridiculously high and it still read data, just again I get the stuck HTTP threads. I'll try this hardware flow control and see if I can get anywhere. Posted at 2017-05-11 by dave_irvine Huh... this is interesting.
Posted at 2017-05-11 by Wilberforce If you look in chrome in the developer tools, in the network tab you can see the requests sent. You'll see the requests that never get fulfilled... As the http server can only handle one request at a time, when they overlap it does not work and buffers get ful and it all goes to custard! One work around is to use github and the github.io with your user name. You can out the CSS and js file and images there, and have the espruino just send the main code. Posted at 2017-05-11 by dave_irvine It definitely can handle more than one request, it just depends on how busy the Espruino is. Unfortunately, reliable HTTP serving is a key component of what I'm working on, I can't just shift the job out to an external HTTP host :) Posted at 2017-05-11 by Wilberforce And you can also use quoted literal for your HTML - so you can then span multiple lines:
Posted at 2017-05-11 by Wilberforce
Can it if the requests overlap? Posted at 2017-05-11 by dave_irvine Yup, heres 1 html file that kicks off 4 concurrent/overlapping requests Attachments: Posted at 2017-05-11 by Wilberforce Thanks. I'll try the code tomorrow. Posted at 2017-05-11 by dave_irvine Oh Gordon you genius! Flow control works, you just have to reconfigure the UART to enable it.
not sure what RTS is, but CTS works fine. Also, looks like we now have the baud range that ESP8266 supports:
From my reading I think the *40 has something to do with the clock speed of the serial line? Because 115200*40 is 4608000, and that is the baud rate I set that got me into my very nasty mess of needing to reflash the ESP8266. I'm guessing the Espruino just can't go that high.
Posted at 2017-05-11 by @gfwilliams Great! I'll add an issue for that on GitHub - adding proper IRQ based flow control is probably not that painful since there's already support for software flow control (which I don't think ESP8266 has). It might even mean you should shift to a significantly higher baud rate without problems. And yes, Espruino can definitely handle concurrent HTTP connections - it should manage about 4 with the ESP8266 in AT command mode. There's no multitasking as such - very urgent tasks get done in IRQs (like getting bytes from serial and dumping them into a FIFO) but the JS just runs in sequence - why it really helps to have a series of small functions that execute quickly, since you're effectively then doing multithreading yourself. Posted at 2017-05-11 by dave_irvine +Gordon I guess there is no way to have flow control closed while I'm trying to pipe a long response back to the client, because ofc the data needs to flow back... would be nice if there was just a way to pause incoming connections! Stuck again! Will your native implementation of the networking help me out of this situation? Posted at 2017-05-11 by @gfwilliams No, it's a bit tricky as you can't inspect the current fifo usage from JS - ideally you'd just pause it for a bit when the fifo started getting full. And yes, the native implementation should - but realistically the addition of the hardware flow control is what you really need. Posted at 2017-05-11 by dave_irvine Also, any idea why I'm getting FIFO full immediately after starting an AP as per my post: http://forum.espruino.com/comments/13629011/ Posted at 2017-05-11 by @gfwilliams
I noticed that too just now - I think it's the big splurge of data the ESP8266 sends out right after it's reset. Most likely it's because of the way data is stored in the UART buffer. UART data is normally packed densely, but if there's a framing/parity error it is also stored in the FIFO, but it takes the space of 4 (sometimes 8) characters - so it doesn't take much of the ESP8266's 76800 baud boot transmission to fill the FIFO up :( There should now be a WiFi build in http://www.espruino.com/binaries/travis/5fd503c0b6ae7a24f044e23fa3f7a8690ce7fed7 If you then try that and then this slight modification of your code (note I'm not using an AP in my case):
It'll enable proper hardware flow control for the Espruino WiFi and it should start working. It now reliably loads all pages for me even with your indexVERYBAD. Posted at 2017-05-11 by dave_irvine Glorious. I had just finished a very hacky workaround, but this works better. Judging by the heat of the CPU I'm going to need a heatsink soon, LOL. Any thoughts on the baud rates?
What is the clock frequency of the UART on Espruino WiFi? I'm guessing it can't be the full CPU clock speed else 4608000 baud would be working which it isn't. Nevermind, some trial and error gives us... Posted at 2017-05-11 by dave_irvine So that, combined with what some might call an 'irresponsible' baud rate of Not bad! Posted at 2017-05-11 by @gfwilliams Interesting! I didn't know what the max baud rate is - I imagine there will be diminishing returns pretty quickly as the rate rises past 1M baud though. The heat'll all be coming from the ESP8266 - by comparison the STM32 doesn't draw much at all. 6k in 1.32 seconds on the low side, but I guess that's actually with multiple HTTP connections? I guess the real win will come for bigger files, so you might get a better experience by inlining your CSS. If you're a total sucker for punishment there's also http://www.espruino.com/Reference#l_E_setClock So you can overclock the chip itself. You might just be able to run the code for 160Mhz (default is 100), but it is a different chip so I'm not sure. Apart from pointing you at the STM32 chip's datasheet on the WiFi board page there's not much I can do to help you there though - that's getting very extreme! Posted at 2017-05-11 by dave_irvine An interesting effect I've just noticed. If I Yes thats over multiple connections. To be honest it spends most of its time waiting while in flow control. Maybe your native network module will help requests run more concurrently. Attachments: Posted at 2017-05-11 by @gfwilliams When you unplug, the console will swap over to Serial1 (you can stop it with I'm surprised it breaks things, but I guess at the speed you're running Serial2 at, it might be that also servicing the Serial1 interrupts causes it to lose the occasional character from Serial2. Such is the fun of embedded software - usually I try and run everything at sensible enough speeds that nobody has to worry about it :) Posted at 2017-05-11 by dave_irvine Ruh-roh. Do not anger the SDcard gods.
time for me to go home! Posted at 2017-05-12 by dave_irvine And after leaving it for a night the SD card works fine again. -.- However, I'm now intermittently getting
this is before I set a custom baud rate, so I'm not entirely sure what is happening here. Posted at 2017-05-12 by dave_irvine +Gordon I think this might be related to the full FIFO buffer. Especially with the v0.50 AT firmware, I think the init string is longer than with v0.40. If I wait for my initial wifi.startAP to fail, and then send an AT command directly, the buffer seems to be full of junk. If I send the AT command again, everything clears up:
Posted at 2017-05-12 by @gfwilliams I guess you'd have to try with Posted at 2017-05-12 by dave_irvine Ok, with the following code:
I see the following:
so there is definitely 'ready' in there, but I guess Espruino is missing it because of the full buffer? I've hacked in a workaround for now. Calling Posted at 2017-05-12 by @gfwilliams I don't know - it should have got that, since it's got a newline before and after. If it's printing it then it's in the buffer and hasn't lost it. Perhaps it just takes longer to boot than Espruino expects - although Espruino does leave 10 seconds? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Posted at 2017-05-11 by dave_irvine
Given the following code sample, I can fairly reliably have all the "stylesheets" fail to load when there is CPU load during try to respond to their HTTP requests.
Dial
var junk = generateJunk(45);
up and down to experiment, I got it as far as 1024 when using indexOK, and up to about 60 using indexBAD.If the indexBAD page loads first time, try refreshing a few times, eventually it should stall out.
I'm not sure if anything can be done here. Ideally no matter how intensive the CPU task the HTTP request would eventually complete.
Beta Was this translation helpful? Give feedback.
All reactions