-
-
I believe StorageFile now allocates at least 40kB for each file on Bangle.js - so it probably isn't that efficient for you!
Oh wow that's pretty crazy. By using normal 'Storage' files we could probably reduce the production of un-erased flash pages by 40-fold, so compaction happens 40 times less frequently. Thanks!
-
Actually have you tried just install default apps from the app loader, and then trying again? I guess it's possible that the Storage got corrupted somehow and this is causing continued compaction errors. Starting from scratch might help.
Yeah I've tried that, it still gives the same errors.
While it shouldn't be the cause of your problems, I'm not sure that's actually going to be the best way of doing things. Internally Storagefile allocates a big chunk of data in order to do appends, so honestly I'd have thought you would be better off just writing to a standard 'Storage' file directly in the first place...
Either just keep everything in RAM if possible, or maybe use Storage.write with the offset functionality: http://www.espruino.com/Reference#l_Storage_write
Hmm... I have thought about that as well. I was concerned that
Storage.write()
might repeatedly rewrite the same page until the 4096 bytes are filled. Is that a problem, and if it is would it be more / less of a problem than using StorageFile? -
@Gordon I'm not sure if this is correct (I am not familiar with Espruino internals after all), most code execution on our app run during event handling, and the errors that occurred with Morphing Clock also only happened during events like button presses, so perhaps the event handlers are not updated regarding the callbacks' locations in storage?
Also, I managed to replicate the problem manually with the following steps:
- Open Morphing Clock
- Open a StorageFile and write some arbitrary data
- Erase said StorageFile
- Call
require('Storage').compact()
- Press BTN1
which throws the following exception:
Uncaught ReferenceError: "fffa" is not defined at line 1 col 3 W+CHARP;var d=new Date();g.reset();g.setFont("6x8");g.setFontAlign... ^ in function called from system at line 1 col 1 fffaff ?[204] ?[204] ?[204] ?[204] ffafffff ?[204] ?[204] ?[204] ?[204] ?[204] ?[204] ?[204] ?[204] ffffa?[204] ?[204] ?[204] ?[204]...
- Open Morphing Clock
-
-
Which exception was that? "attery" is not defined?
So just to be clear, you ran require('Storage').compact() and there weren't errors, but then when you long-pressed BTN3 you started seeing errors, even though the app worked fine before the storage compact?
Yes. To be clear, I was on the morphing clock app just so our own app wouldn't be running during compaction (as the instructions above seem to only ask to run the app after compaction). The error I saw was indeed the above
"attery" is not defined
. It didn't break the app per se, only the current running instance of the app. I did another reset and it worked fine. For context I had ~300 files (260-512 bytes each) in storage, in total probably < 200 kB.How did you check the contents of the file? By loading it again with the IDE?
Or was it just that you saw \ff in the stack traces from errors?
By opening the file using the storage tool in the IDE. Just to be clear this is our own app's file, this and the
"attery" is not defined
error (which happened while running morphing clock) were two separate issues. I knew it was \ff because the file viewer in the IDE was showing hex alongside ASCII.By the way I did the above compaction steps again, and this time a different error (once again from the morphing clock app):
Uncaught ReferenceError: "fffa" is not defined at line 1 col 3 W+CHARP;var d=new Date();g.reset();g.setFont("6x8");g.setFontAlign... ^ in function called from system at line 1 col 1 fffaff ?[204] ?[204] ?[204] ?[204] ffafffff ?[204] ?[204] ?[204] ?[204] ?[204] ?[204] ?[204] ?[204] ffffa?[204] ?[204] ?[204] ?[204]...
It happened after I moved my hand, instead of after long pressing BTN3.
If you can actually reliably get the file corrupted by running compact then that's great - if you can send me the steps (privately if you need to keep your code private) such that I can reproduce it then it'll be much easier for me to fix.
The corruption is not actually reliable. It only happened the first time I tried running compaction. The next three times were fine. That said every time I did it the morphing clock app seems to throw errors, so that one is reliable.
As for the replication steps:
- Run our app, and start logging. Since I haven't yet sent you the code, the way this works is using a combination of StorageFile and normal fixed-length files. StorageFile (in base64) is used to allow for appending, and once that StorageFile reaches a given size limit (currently 349) the content is converted to binary and moved to a fixed-length "checkpoint" file.
- Leave it running until it starts throwing errors continually.
- Reset Bangle.js and go back to the morphing clock app.
- Perform the compaction steps above while running morphing clock
- I'm not sure what will fail here. 3 times out of 4, long-pressing BTN3 throws an error, and 1 out of 4, moving the device throws an error.
- Run our app, and start logging. Since I haven't yet sent you the code, the way this works is using a combination of StorageFile and normal fixed-length files. StorageFile (in base64) is used to allow for appending, and once that StorageFile reaches a given size limit (currently 349) the content is converted to binary and moved to a fixed-length "checkpoint" file.
-
-
Unfortunately, the errors produced are rather different every time the code changes. It does seem to be happening in the same module (we're using Webpack), and that particular module does contain a recursive function along the lines of:
class C { ... f() { ... somePromise.then(() => { ... f() }) } .... }
However, the errors occur at other functions, some only ever called before said recursive function, and some always called after it. One possible commonality (I've only just noticed so I haven't been able to verify just yet) is that they all seem to use promises. Then again, it might simply be because that particular class uses promises in a few different places.
By the way, after trying to follow the above instruction to do storage compaction, I tried to reset (long press BTN3), and got the following exception:
>require('Storage').compact() =undefined > Uncaught ReferenceError: "attery" is not defined at line 1 col 3 W+CHARP;var d=new Date();g.reset();g.setFont("6x8");g.setFontAlign... ^ in function called from system at line 1 col 1 attery()*(s-12)/100,y+17);g.setColor(-1);}Bangle.on('chargin... ^ in function called from system
and when I tried to run the app it turned out the file was corrupted (with sequences of
\ff
at two places in the file). Is this to be expected? I repeated the steps and it the file was not corrupted the second time, though I got the same exception from long pressing BTN3. -
Hi Gordon, thanks for the reply. We do write to flash very frequently, but it is important for us that it does that. Still, thanks for your advice regarding power usage and longevity, we now know to watch out for those. That said, we are using firmware 2v09, so maybe something else is happening? Thanks.
-
I have been working on a Bangle.js app for work. After leaving the code to run for a while, the app starts throwing errors continually (probably once every time some event is fired). The errors thrown were very peculiar to me. For example in latest build:
Uncaught ReferenceError: "ointStep" is not defined at line 1 col 1 ointStep(){var ^ in function called from system
(where the function in question is supposed to be
notifyCheckpointStep()
, is not even a function call but rather a method definition within a class, and is most certainly not at line 1 column 1)and
Uncaught SyntaxError: Unexpected end of Input at line 1 col 30 t c=0;const l={normal:1,move
It almost seems like Espruino is reading the program as a 30-byte fragment of the full program, and crashing because the resulting syntax within the fragment is invalid.
We know for a fact that the program file itself is intact, as resetting the Bangle and starting the app again works fine (until a few minutes later when it starts throwing the exact same errors again).
For context, the program uses a relatively large amount of RAM, with only less than 300 blocks left out of the usable 2100 blocks, and that's when no function is running and everything is just waiting for events. I don't know exactly how much memory is used at maximum. We have already run into other problems caused by low free memory (which fortunately we have managed to work around) so I hope this is not yet another one of them.
May I ask what causes this, and how we could solve this problem? Thank you.
Ah that sounds very robust, thanks!