GPS code/module/library leaking memory before 'satellite lock' occurs #570
Replies: 12 comments
-
Posted at 2014-06-19 by @gfwilliams Hi - thanks for letting me know, and for including the traces... That's an odd one - there doesn't appear to be any obvious cause of the leak. The GPS code is actually pretty simple, see: https://github.com/espruino/EspruinoDocs/blob/master/devices/GPS.js All I can think is that the GPS doesn't send any newline characters while it is searching for a lock, but that doesn't explain the permanent leak. Unfortunately as it is, it's hard to see what the problem is, or what the data being read is. Can you try:
Then you should be able to check on what
That'll spam loads of stuff over the console, but it will show you what data Espruino is getting from the GPS while it's waiting for a lock. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by user6350 I recently build a GPS data logger , based entirely on Espruino Javascript, recording data onto a SD card at a 10 Hz rate. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by user6350 Please find here the example firmware |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by user6350 File not uploaded, so I copied the code here.
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by user6350 |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by user6350 /Users/gv/Desktop/screenshot_667.png |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by user6350 Please find here a log view corresponding to 4 different acquisitions or travels.Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by azrobbo Thanks folks for your feedback and info. @user6350 - Thank you so much for providing this awesome code-base! I'll definitely leverage what I can from that once I start working on the actual GPS project again. (Right now I'm kind of obsessed with understanding what is causing this leak.) @gordon - I'll help out however I can to track down this memory leak, as it might effect other modules and users as well. I have limited time today, but I was able to log the direct serial output of the GPS before and after 'lock', so we can examine the data-stream. Here's a sample from the data-stream, before GPS-lock
Here's a sample from the data-stream, after GPS-lock (Note: the checksum bytes won't be accurate, as I've anonymized the location data.)
I manually executed some of the library definitions with pre-lock data. Note: I have a similar output generated with post-lock data, but since it executes as expected, i'm not sure it adds any value. I can post it if anyone thinks it will help.
I'm wondering if there could be a leak caused by one of the string parsing functions used to calculate the latitude, longitude, fix, satellite, or altitude vars, when using a '-1' parameter and/or when the result is "NaN". Since these functions execute several times a second, even a small leak would become significant very quickly. Alternatively, could this be some sort of buffer overflow with the Serial Port? I've verified that my module is running at 9600 baud, so I don'd see how this is possible. I have the following tests planned for tomorrow:
I believe these steps should help us determine the root cause of the leak. Are there other test that I should try? Are there other additional environment settings that I should capture in addition to process.memory() and trace() ? |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-20 by @gfwilliams @azrobbo thanks for your help! you were spot on about it being nothing to do with the GPS or Serial. It's I took your code, ran it 10 times, and measured The new version of Espruino's got some pretty big changes, so it might be a while before I release it, just to make sure it's ok. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-20 by azrobbo @gordon thank you so much for tracking this down! I can easily code around this until the next release comes out. Cheers! |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-08-20 by roy.emmerich Edit: My apologies. I found it :) ========================= I have one question concerning your code. On lines 38 and 39 you have the following function calls:
However I don't see where this tracking function is defined. Could you please clarify? Many thanks. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-08-21 by @allObjects @user6350, working on getting Espruino to understand my 'old' marine #GPS, I read through your code in post http://forum.espruino.com/conversations/1578/#comment26928. I tried to understand getUTMLatitudeZoneLetter(latitude) {... #latitudezone function. Analyzing the implied algorithm and underlaying data values and structure, a How about:... popped up in my head:
And this would be the code:
The two-termed logical AND expressions, for example, To verify the How about, I first morphed the given, quite redundant code into a more concise form - of which one you find below.
After that it became clear how the arithmetic version would look like for the computational approach. Separating the defined range from the undefined ones is though still best done with the comparison approach. The values in the defined range are converted by a formula into range of 0..18, just parallel matching the "CDE...X" string. Note that letters I and O are 'skipped'. Luckily, the irregular interval [72..84] N still works for the divide by 8, because the top value is less than 2 * 8 and collapse with Math.floor() to the the range of [72..80). I'd like to point out a nice, genuine JavaScript language behaviors: #operatoroverloading, and #typeconversion. You may wonder about the multiplication by 1 in the correction term (latitude * 1 + 80) to base the defined range to begin with 0. JavaScript has the nice feature - Java-ists call it flaw - of going further with auto type conversion than many other languages - especially (strongly, static) typed ones. When the function argument latitude is as a string - which it most likely is when reading plainly from the wire) - then types matter expressions operator overloading. Therefore, the value of (latitude + 80) with latitude having the string value "-80", the expression ("-80" + 80) evaluates to "-8080" string, because the "-80" is a string type and defines the type precedence of the operator overloading: + operator becomes string concatenation and hence the result is a string too. JavaScript will convert the number 80 into a string to accommodate the concatenation. Reordering and taking the number 80 first - (80 + latitude) - does not help either. The number 80 is operator overloading happens again to accommodate the "-80" string. Multiplying the latitude by 1 - (latitude * 1 + 80) - solves the issue with no (real) harm or value effect, even when latitude is (already) a number. Multiplication has no operator overloading and numeric is the only option. The "-80" string is converted to the number -80 to accommodate it and the expression evaluates to 0 - just as expected ;-). Furthermore, notice the opening parenthesis on the same line of the return statement. This is because of another JavaScript genuine 'feature', or #returnpitfall, #jspitfall: If a line feed follows a return, the return is considered as complete and the function returns #undefined, no matter what keeps going on in the next line(s). I could have of course put something relevant after the return keyword to avoid it, for example, the logical expression for separating the valid from the invalid ranges:
Try it yourself with the uploaded .html file... ;-). For some (random and visualizing) unit testing I like to have a visual UI environment that I can drive with HTML5/JavaScript. Therefore I created a simple file-protocol served .html file. See uploaded screenshot and .html file. You can download the .html file, look at the various implementations, open it in a browser (with no harm) and play with it.Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-06-19 by azrobbo
Hi Folks -
Today, I encountered a memory leak with a simple bit of code that's interfacing with a GPS module using the GPS library. Specifically, about 2-3 blocks of memory were leaking every 5 seconds (or so) until the GPS got a 'satellite lock'. This may have something to do with how my module transmits data pre-lock, or could be a mistake that I've made (as I'm new to Espruino) . In case it's relevant, the GPS Module that I'm using is the Adafruit 'Ultimate GPS Module' with MTK3339 chipset.
Initially, I thought the memory leak was something in my code, and I was in the process of tracking that down when the GPS got a 'lock' and the memory leak stopped. I stripped my code down to the minimum, and grabbed three process.memory() and trace() dumps, two before the 'satellite lock', and one after.
Here's the code that I was testing this with:
Immediately after uploading the code, process.memory() returned the info below. The matching trace file is called 'trace-start.txt'
A few minutes later process.memory() returned the info below. The matching trace file is called 'trace-422.txt'
Finally, the satellite locked when 576 blocks of memory had been used, and the memory leak stopped. process.memory() returned the info below. The matching trace file is called 'trace-satlock.txt'
I'd be interested in anyone's thought of ideas on this problem.
Thanks.
Attachments:
Beta Was this translation helpful? Give feedback.
All reactions