Array of Strings and in and out of 'out of memory jail' #317
Replies: 15 comments
-
Posted at 2014-10-01 by DrAzzy (Mostly off-topic (as the topic is the bizzare behavior you're seeing) - are those the strings you're saving? I assume it's something more substantive than that - if that's all it is, you could write a very small function to get the string from the index number, and dispense with the array entirely) |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-01 by @allObjects @drazzy, you are absolutely correct... the strings are way more substantial than algorithmic derivable values. The actual strings are shown in the code snippet below, which also includes the join-split and store operations in the ini() method. The 'KeyNMO'-thing was just a placeholder to imply that there are many of those - relatively short - strings. I did run out of memory when the strings in 2nd and 3rd block - which correlate - were less then half in count. The characters in the string are encoded values. The encoding is preliminary - but human readable and quick to interpret - and the encoded (unsigned) integer values are in ranges from 0 to 16, 32, and 96. I'm thinking of running them through a generator to compact them even more, and then use them as typed arrays. It would be interesting to elaborate on various implementations and the overall impact - not just in regard of the 'data and its structure', but also the dependent algorithms and their performance. For runtime - after initialization - the values are neededas individual addressable items. At one time I thought I could leave them as complete strings (joined) and access with .substr()... May be it will become possible after compacting them and then 'pay a bit more for it' while repeatedly extracting values. At a later time in the project I will be a more verbose about the strings' purposes. ;-)
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-01 by @gfwilliams Hi, I think in this case the issue might be that you're defining the keys inside the function. This means that the function itself is using a lot of memory (probably more so that the actual data because of the padding). You could check using Then, when you run that function you've got two copies of the data - one in the source and one that had just been created. If you defined the data in the root scope then Espruino would discard the source after executing it, leaving you with just one copy. It'll be faster too. You'll find that storing a few large strings (like you're doing) is probably more efficient than a small array of strings. You could save even more memory by just iterating over the array rather than joining it into a large string first too. Having said that, using large chunks of data like this really hammers home just how small 48kB is. Microcontrollers just have fairly limited resources, and you have to adjust your coding style to fit within their limits. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-01 by @gfwilliams Just to add, have you seen these pages: They might give you some hints about how the interpreter works... |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by cephdon If we had the ability to do a relative seek in a file, or the ability to move to an absolute position (forward and backward) in the file, then we could build a relatively unlimited (from the perspective of memory) key value store (or simple db). It's easier if it's relative, though. Basically, you store in a file(for each entry): It might not be as fast as an in memory array, but with a 32GB sd card, you could store and search much more than the memory available. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by @allObjects I'm recalling having read them when I came across Espruino the very first time - even before having had a board in hand. I glanced over it when replacing my first [1v67] with [1v70] with enhanced memory management. I though did not pay as much attention until now, after encountered out of memory.
Arthur Schopenhauer - 1788-1860 Humans have great difficulty to internalize and to be sure of what they hear or are told - and in turn to adjust their actions - once having experienced something though by themselves, they stick stubbornly with the cerntainty of that personal, individual and often only exemplary experience - and I'm no exception from that. Absolute doubtlessness - absolute certainty - gained by very own experience made in far or near past under then circumstances make oneself a prisoner of that past and blind to accept present and future options and no-options / constraints - not noticing that circumstances most likely have changed. Blind spot is another term for that. With a fresh look at the implementation / internals / performance, I will elaborate on code variations empirically in the beginning, and over time more theoretically - in an a priori way - the more I (really) understand. Usage of a very high-level language let's one quickly make things happen and equally quickly forget what is really going on under the hood. Back to the roots is as bloody-red as the red beets themselves... but it is fun. Regarding temporary memory usage, I was thinking of using the require() and then the un-require() - of which I read about in some posts or tutorials, but can not recall top of my head the actual function call.... will come back and edit the post. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by @allObjects @cephdon - you are absolutely right - when there is no time constraint using the practical unlimited space of the SD card is a way out. For the first of my three blocks of data this is a valid approach. For the second and third one, access and process performance are crucial. Therefore they have to live in the memory. If all options fail - space and time - I may resort to inline assembler creating the values from a very compressed, byte based/bit banged memory chunk, and pass them back to the JavaScript context. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by DrAzzy In-between SD card and RAM, you could use something like an AT24-series eeprom for additional storage? |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by @gfwilliams There's also the ability to store the data in Flash memory. If your board is one of the ones that actually has 384kB (I think all of them do!) you've got at least 100kB at the end to fiddle with, and you can use peek to get at the data. @cephdon - just to say you can still open the file and |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by DrAzzy Bigram builds tell it the chip has 512k, and they seem to work... |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by @gfwilliams Wow, ok - so yeah - lots of data. I'd be tempted to keep telling the bigram builds they only have 256k though. That's solve this problem you're having with upgrades breaking |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-02 by DrAzzy But then it wouldn't have room to save() the 64k of program code, would it? |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-03 by cephdon @gordon nice! |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-03 by @gfwilliams @drazzy, good point :) By turning on '-Os' you could still get it all in if you wanted though. It's just that with the current setup, the memory you can use is somewhere between addresses 220kB and 430kB - not as easy as just saying 'anything past 256 and you're fine'. @cephdon it's absolute positions. 'skip' can skip forwards for relative positions, or you can always keep track of the file positions yourself. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-10-04 by cephdon @gordon, So it could still be done. Awesome. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-09-30 by @allObjects
Some pointers about the implementation of JS in Espruino is very welcome here. I provide an example from code I'm working on (Part of this conversation - including some helpful responses - began in http://forum.espruino.com/conversations/255757/ about GPS module and Extensions there of. It is now its own conversation for separation of concerns.)
I needed an array of strings - keys - for processing. So I created an array of strings in the source code and it got me quickly out of memory ( #outofmemory ) into the 'out of memory jail':
In a desperate move - with no real rational but just some guessing - I chose to group the keys w/ space as separator in fewer strings and apply some joining and splitting before processing to keep the same algorithm (because of performance) - and 'miraculously - it got me out of 'out of memory jail' (The joining-splitting with/by space is possible because the keys cannot include spaces):
There are several conversations out there about memory and out of memory and I reference them in this list:
GPS code/module/library leaking memory before 'satellite lock' occurs
Out of memory?
But none of them can explain the following:
You may have notice in the above code the line
keys = keys.join(" ").split(" ");
Even though I then kept/stored the joined-splitted-processed array, I was kept out of 'out of memory jail'. It must have to do something with how source code of arrays of string literals is pulled in and hold onto.
What is the 'somewhat puzzling' key-note to take from this experience?
PS: I had temporarily similar experience as mentioned in 2nd reference above, even though I used the fixed version of the .indexOf(...) - [1v70]. The issue showed in the GPS modules handleGPSLine when going for the decimal points with indexOf('.') in the lines received from the GPS receiver. Could it be that the .indexOf() String method is still a bit 'weak on its legs'. Having read about it I felt it had something to do by releasing the search argument string... but I may be totally wrong about ti. As said: it was temporary. Nevertheless, observing it cannot hurt.
Beta Was this translation helpful? Give feedback.
All reactions