Polling/Vector Speed
Pages: 1 2
Malcolm Hussain-Gambles (1596) 811 posts |
It would be lovely if RISC OS could poll (e.g. using vectors etc. in modules, or wimp_poll_idle) at a finer rate than 100Hz. I’m sure there are other uses, but having faster networking for NAS devices etc. would be great [especially on the “next-generation” machines] At the moment sitting on the NULL event is the only way I can see to get vaguely reasonable speeds. It doesn’t seem to have a seriously detrimental effect on desktop performance, but it just seems wrong. So I’m hoping there are other reasons people would like this, would it be a candidate for a bounty? Whether it would need wimp_poll_not_so_idle and os_finevector – rather than changing the existing calls, I haven’t got a clue! |
Rick Murray (539) 13840 posts |
I think the “typical” way around this is to wrap the data transfer stuff in a module which can work in the background (maybe off an interrupt or event) which buffers the data and then sets a pollword for the Wimp task to notice and respond to. Certainly, one cannot expect RISC OS to poll within any specific time frame – ChangeFSI and NetSurf both are known for hourglassing, and it’s all bets off if something pops up a standard error box. ;-) |
Rick Murray (539) 13840 posts |
To continue – one of the problems of RISC OS is that there is no reliable mechanism for calling a piece of code after a set amount of time has expired. Sure, we have CallAfter and CallEvery to call every >=2cs and we could hook to TickerV for centisecond timing, but the problem is that we may well be called in the middle of some non-reentrant code which seriously limits what OS facilities are available – which is all the more important these days as USB devices are implemented as filesystem devices, and the filesystem just can’t be used in that way (it’ll throw “Filecore in use” errors). So we have our nice CallAfter, CallEvery, or TickerV and we need to use them to schedule a Callback. The difference here? Callback gets back to your code when RISC OS is “idle” and it is safe to use most of the OS facilities. The caveat? It will get back to you in n where n can be anything from nanoseconds to entire seconds. There’s no way of knowing. Couple this with borked events (I’ve never ever had any joy with being notified of MIDI data via USB, I still poll the device as that’s what reliably works even though it sucks as a method), it does make some aspects of programming a whole big bag of joy. ;-) |
Malcolm Hussain-Gambles (1596) 811 posts |
From my perspective, I can predict fairly reliably when there will be data on the sockets to read. newsuk does this to some extent by modifying the poll_idle time depending on the amount of data read off the socket. However for faster reads the only choice is to capture all polls, on a RISC PC this may not be many – however on a pandaboard around 1 in 10 polls are pointless and on the upcoming machines this is likely to increase. I don’t really care if some other program causes jams or error boxes, that will freeze the download – irritating, but nothing I can do about that. My understanding about the poll word, was the wimp task has to be polling for it to spot it? If that is the case it’s kind of pointless, as it would probably be just as efficient just to do a select (for client side, possibly not if you were doing server side stuff waiting for incoming connections) |
Colin (478) 2433 posts |
You only need a wimp poll event (pollword non zero or null) to determine if data is available in the first place. After that you keep reading the socket until you receive all of your data or get an EWOULDBLOCK message. If you feel that you are going to hog the processor too long add a wimp poll every so many bytes or cs. You don’t need a wimp poll for every data read/write. |
Malcolm Hussain-Gambles (1596) 811 posts |
That’s not really true, you can only read a maximum of 17k at a time. So you have to read, then return control to the wimp – otherwise you lock up the machine (e.g. downloading a 2GB file, it would lock up for quite awhile) |
Colin (478) 2433 posts |
If what you say is true then networking wouldn’t work in a single tasking program which it does. The fastest way to transfer data is to continually read data in a loop. Wimp polling is just an extra function in that loop which slows your loop down. |
Rick Murray (539) 13840 posts |
It is better for your transfers to poll (not pollidle) at a rate that depends upon how fast data is coming. The problem is when you do not have data being transferred – do you keep pollidling or do you wait for an external notification. Both are workable, though which you use depends upon how the code is written – the poll word method presupposes some sort of back end. |
Malcolm Hussain-Gambles (1596) 811 posts |
Sorry I’m not explaining, of course it will work in single tasking – that’s exactly what my current d4r program does. @Rick is it possible to poll at a certain rate?!!!! I’d never even thought that was possible! |
Colin (478) 2433 posts |
Which is why I said that if you are hogging the processor you need to add the odd wimp poll during the transfer. Your method seems complicated to me. If you are waiting for data, wait for a null event with wimp_pollidle. Once you are receiving data keep reading it until you have it all. If you feel this hogs the processor too much throw in a wimp_poll at a frequency of your choice. You can’t get high speed and multitasking – it’s a trade off one against the other. |
Malcolm Hussain-Gambles (1596) 811 posts |
I’ve managed to get close to high speed and multitasking well. I agree my method is complicated, but it seems to sustain a good balance. The other issue is that writing to SD Cards is slow and also I suspect it shares the same channel as the ethernet, hence the use of a secondary (large) buffer using flex. The complicated nature of this, is why my end goal is to have this as a module. That way the whole complexity is hidden. |
Rick Murray (539) 13840 posts |
Depends what side you are looking at it from. You can pass a number of centiseconds to PollIdle; but you can also keep track of the time taken in your program – for example you can set up a CallAfter to notify you in, say, 5cs, at which time you set a flag for the main thread to notice and when it does so, you poll (normal poll, to return on a Null event for the next bit).
Shouldn’t it depend more upon how fast the machine can respond, not how fast the transfer is running at? Else you run the risk of replicating that annoying NetSurf behaviour where it whinges about how slow the disc cache is on a system that more than likely would benefit from a cache on anything faster than a floppy disc… Yes, SD writes may be slow. But, then, so is my internet. It runs at 2mbit flat out, and I don’t think the Pi (Vonets adaptor, very weak signal) has ever managed anything close to 1.5mbit (I’m guessing this is something in the order of 180KiB/sec?).
I think RISC OS allocates 16KiB for each socket, though I cannot check as this crashes the machine when used in a TaskWindow (neverending errors), and returns zero (!!?) when used in ShellCLI and then the machine crashes.
Useful. For anybody interested, returning from ShellCLI reports that Application may have gone wrong (but there’s no indication of what application is faulty) and if you press Quit a few times (this is a repeating error), the report is: Error If you instead press Describe, the message is SWI &205110 not known. If you dismiss this enough times, it goes away and then “the desktop collapses”, namely everything crashes in turn until you are left with a blank black screen and no way to get out of it. Here’s a video I made earlier: http://www.youtube.com/watch?v=ALV3uLjI0Do You can, if you are brave, adjust the size of the socket using setsockopt and the “limit” mentioned in the PRM is applied in the sbreserve() function and the value “sb_max” is defined in TCPIPLibs:sys.h.socketvar as
Oh, yes, I’m having lots of fun seeing what doesn’t sanitise inputs so the end result becomes a horrible gooey mess. ;-) |
Colin (478) 2433 posts |
How is that any different than just reading the monotonic time every null event or indeed setting pollidle so that it polls every 5cs? Seems to me that you are just creating a 5cs clock. Setting a flag in the background won’t improve the latency between 5cs being up and you being notified of it in a null event. The only reason to use a module – which you would need for callafter – is to be notified of events via pollword non zero which has the effect of giving your event top priority ie pollword events happen before desktop events, null events after. |
Rick Murray (539) 13840 posts |
Simple. This is in code like the following: while there is data read some data from the socket if we have taken too long wimp_poll endwhile So, it isn’t done in the regular polling loop, it is done when you are active in order to determine when to force a poll so that the system will keep running while downloading something large; and being based upon time, it will be more consistent than polling every n KiB (which will be highly dependent upon connection speed).
That’s exactly what I’m doing.
You do know, I trust, that if you are not writing an application in BASIC and you remove the event prior to polling (if it is pending), you can schedule a CallAfter into your own code in application space? No module needed, and yes, I’ll grant you, it would be pretty dumb to wait for a poll event to know when you should poll. That doesn’t make any sense. ;-) So your code could check for the “timerexpired” variable in its activity loop, and if found to be non-zero, perform a poll. And your CallAfter code? A tiny bit of assembler that will set the “timerexpired” to non-zero and also set “timerpending” to zero (so you know you don’t need to clear it before polling). While this is more complicated than simply reading the ticker yourself, it does remove the overhead of calling OS_ReadMonotonicTime every time you go through the motions. Whether or not you think this is a concern is up to you. ;-) Calling the SWI repeatedly would have the same effect; thus it is why I suggested both options. Check your own time use, or let the OS prod you. Either will work… Thus, your activity could be something like: set_timer while (timerexpired == 0) do_stuff endwhile or: timenow = ReadMonotonicTime while (ReadMonoticTime < (timenow + 5)) do_stuff endwhile |
Colin (478) 2433 posts |
Doesn’t matter where you do a wimp poll you can write the code to use the main loop if you are that way inclined – I used a multi threading system in FTPc all driven by the main loop. I agree that time is the limiting factor and not transfer rate.
As you show using a OS_ReadMonotonic time is the same as using callafter so why use it when we already have a monotonic clock to time things, and no I don’t think it’s a concern calling OS_ReadMonotonic time given the number of swi calls used in interrupt contexts. Most OS_ReadMonotonicTime calls save a wimp poll – the main user of cpu time – and the time taken by the call will probably be taken up by the background process filling the buffer. Just my 2p I just don’t see the need to over think this. On a minor point I think you should use while (ReadmonotonicTime – start_time < 5) as it copes with time wraparound. It may not matter in this case but one day it might. |
Malcolm Hussain-Gambles (1596) 811 posts |
@Rick Why not just come out and say it? It’s not being brave, it’s just a sign of insanity. So that sounds just up my street ;-) The main reason for being a module is to allow this complex and nasty stuff to be totally abstracted. |
Rick Murray (539) 13840 posts |
Sometimes the harder ways can be more fun to play with.
Good luck with that. If reading the buffer size trashes the machine… ;-)
Not really. Remembering the old Google Reader and to a degree how Google’s News app behaves – I would say it connects to retrieve the articles, then defers the images until they would actually be visible. There is no point fetching an awful lot of images for things the user may not even look at. For example with Google News I have Headlines, UK, Sci/Tech, Health, Europe, France and Japan as my categories. However the main content that I look at is the composite view of the top few items in each category; and the times that I look in categories, I rarely read the Health one. It is only there for big stories like “Coffee proven to make men impotent” followed the next week by “Coffee proven to have no effect on sterility”, you know how it is…
;-) I felt like that the last time I went near the font manager.
Background downloads FTW! |
Malcolm Hussain-Gambles (1596) 811 posts |
I agree the harder ways are far more interesting. Trashing my machine is a normal day for me. One of the other things you can do is check that http headers to see if they have been updated, for both the RSS and the images. Background downloads is definitely the goal, no worries about SSL/TLS, no worries about anything. I want this data, now please get it….I hope I get there! |
Rick Murray (539) 13840 posts |
That is quite often the case for me – though trashing things is… rarely by intention. More a case of the infamous Tea Buffer Exhausted error.
Well, there is logic to it. Unless your code is completely self contained and won’t have any external input or user facing API, you cannot guarantee that the input is going to make sense. Sanitising input is something RISC OS perhaps ought to do more of. ;-)
Oh, I don’t know. All the people who were saying how much better Opera was than Firefox were silenced in 2010 when it was discovered that a problem in header parsing could lead to the browser being hijacked (remote execution). In order to downplay this, Opera said that it would rarely be a serious security issue as the browser would crash or be terminated. Unfortunately they were relying upon DEP which the lower-end systems either didn’t support, or only supported for specific tasks. In other words, the only safe option was to cease using Opera until the problem was resolved. Buffer overflows and the like are almost always the cause for zero-days. In our grace, to be able to attack your program (or NetSurf, etc) through a buffer overflow – should one be discovered – would require extensive knowledge of how RISC OS uses the stack, how to insert code and jump to it, and so on. There are many more lucrative targets and easier ways (like an app that just requests details of your contacts, etc). With my server (the one very briefly shown in the video linked above), I receive countless uninvited visitors. Thankfully most are silent because the login process doesn’t look or feel like a Unix login so the script obviously stalls. Unfortunately the script is stupid and frequently the same IP will repeatedly connect until the “firebomb” trap is triggered, at which point the IP address will receive a rejection notice (and they carry on trying to connect for a while). Thankfully nobody has tried to do malicious things yet, but I cannot assume that they won’t. I might dig up my VisualBasic install to see what happens if I dump large amounts of data to the server in one glob, and other nasty stuff like that… I am not going to try stuff like flood ping with malformed packets – that’s out of my hands. Let’s hope the Internet module isn’t (too) buggy.
Not to mention the variety of different setups that you may encounter – a 30-something MHz ARM6 is going to have a little less oomph behind it than a Pandaboard. Likewise, what might work nicely on a 20 megabit connection may be horrible at 33 kilobit (modem speed).
Definitely.
Theoretically? Maybe on the sort of hardware Google and Facebook use; I think RISC OS would flake long before then (isn’t there a limit something like 56 handles at one time? or was that the DCI2 stack?).
Mmm, NetSurf’s RISC OS caveats section says that the number of sockets that can be open may be as low as 64 [ http://wiki.netsurf-browser.org/Caveat_RISC_OS ]. I can’t find any specific mention of socket limits in any official documentation… suffice to say that 3000 at once… it ain’t happ’nin’. |
Malcolm Hussain-Gambles (1596) 811 posts |
The other nice thing is it’s likely, given the workload and given my internet speed – It should probably “feel” like 3000 concurent downloads. As far as different CPU speeds, I do test my programs on a RISC PC, Pi/Pi2 and pandaboard. |
Alan Robertson (52) 420 posts |
This. +1 |
Malcolm Hussain-Gambles (1596) 811 posts |
The next on my to do list is pipelining – this should also reduce the number of connections vastly, whilst still allowing high concurrency rates. But slightly back on thread, it would be lovely to have a finer polling speed! |
Colin (478) 2433 posts |
Do you mean finer polling speed of finer clock. You can use the hal timers for a finer clock. I can’t see any use for a finer wimp_pollidle. As I see it if you are reading data you always want wimp polls that you call while reading to return null events as soon as possible so you need wimp_poll. If data is not available notification of available data can be achieved via the internet event and pollword non zero which informs your program of data as soon as possible. Either way your program gets cpu time as soon as possible. If you are concerned about receiving a null event where no data arrives what is the problem file transfer is a legitimate use of null events if you can’t use them then when can you use them? May as well deprecate their use. |
Malcolm Hussain-Gambles (1596) 811 posts |
At the moment I have to use wimp_poll with null events and dis-guard 90% of them. |
Colin (478) 2433 posts |
If you are getting null events where you don’t have any data then you don’t need to use null events to continue your thread. You can use pollword non zero and the internet event to tell you when data is available. Personally I don’t care if 90% of null events do nothing the computer has to do nothing somewhere. |
Pages: 1 2