Avatar for charlie

charlie

Member since Jul 2023 • Last active Feb 2024
  • 5 conversations
  • 28 comments

Most recent activity

  • in Bangle.js
    Avatar for charlie

    Thanks for the response. What situation would you want to turn on the gps and have something else turn it off? This is why I wondered if app id was legacy and was always being injected anyway. It means a widget could turn the gps off for my app without me knowing (not sure why they would...but they could).

    I also feel like widgets should be restricted to showing information and not changing any.

    If a boot app is managing power and says "no sorry you can't have gps on at moment" it can't switch it off until my app exits?

  • in Bangle.js
    Avatar for charlie

    I was hoping to understand abit more about what happens when you exit an app and return to the main screen and what role appID plays in functions like the one below, if any.

     1. @param {boolean} isOn - True if the GPS should be on, false if not
         * @param {any} appID - A string with the app's name in, used to ensure one app can't turn off something another app is using
         * @returns {boolean} Is the GPS on?
         * @url http://www.espruino.com/Reference#l_Bang­le_setGPSPower
         */
        static setGPSPower(isOn: ShortBoolean, appID: string): boolean;
    
    1. Is there an "onExit" type event you can subscribe to so can do things like saving app state before it closes?

    2. If I don't set the app id is it auto injected?

    3. How uptodate are the comments on functions like "setGPSPower"? I had assumed that once you exit an app to the main menu everything is reset to how it was before you opened the app. The comments kinda hint that multiple apps could be open at the same time. In what scenario would this happen? Widget?

  • in Bangle.js
    Avatar for charlie

    Oh that's ok then. If nobody reads the code it can be as slow and
    inefficient as you like.

    I think you know what I meant. The produced code doesn't matter as much as the thing producing it, which is dependent on which javascript version you want the compiled code in and what other compile settings you have.

  • in Bangle.js
    Avatar for charlie

    It's more frustration at the TypeScript compiler
    Typescript is a game charger for large scale javascript applications. Having type safe code saves so much time on testing and debugging. This is why its built in as standard now to the default react and angular boilerplates. Its also why python is introducing typing.

    ingenious ways to make JS code as large, incomprehensible and slow as
    possible

    Its not built for people to read the compiled code. In my setup its not just typescript. Webpack is doing the module splitting, minification etc. I also doubt I have it set up optimally.

    So while you might be frustrated with Typescript, JavaScript isn't compatible on its own with making large scale stable applications. This is not just my opinion but an opinion held by the majority of leading tech companies using JavaScript.

    ..and just on why abstractions such as "isEmpty" are needed/good practice. If you have a large application with many developers working on it. What does it mean for an array to be empty? If its a preset length and each value is undefined is it empty? Or is it an array of undefined values. It doesn't matter which is true as long as its consistent across your app. The only way to do this is to create a single function everyone calls. This has other advantages. You can have unit test coverage so that if someone finds a faster way to determine if an array is empty that function can be rewritten and the unit tests remove any worry or time taken to test the new version. The person using isEmpty doesn't have to see the code or care how the code works, or what it means to be empty.

  • in Bangle.js
    Avatar for charlie

    So it's 8x slower than just using an Array, and honestly I'm amazed
    it's that good.

    At first I did just use an array but I need to limit the size otherwise the mem is very quickly consumed (think wanting to sample gps data, but only recent as you want to reduce noise). You are speed testing two different things. You are saying pushing to an array is quicker than pushing to an array and then pruning it. Which is obviously true. If you have a quicker way of pushing and then resizing that would be more constructive.

    On Espruino as far as I can see you could just use Array directly, and
    if you really need to limit the size of the queue you could override
    .push to just call splice after it to limit the length.

    I am literally doing the same thing as splice after push (via shift). Originally I extended Array rather than having an internal array variable but the espruino compiler isn't releasing memory when splice or shift.

    I mean, you look at isEmpty, it's calling this.any() which calls
    _this.length which is a getter which calls this.internalArray.length. It's just a nightmare - it's like someone wrote the code specifically
    to waste CPU cycles - even on Node.js it's going to suck
    If I want to know if my array is empty I need to do a check in my code. I still need to call array.length. I could repeat this code every time I want to check, it wouldn't speed up the processing, or I can add an additional layer which can be individually unit tested and optimised further in future.

    Ultimately you might save some cpu time with large chunks of repeated code. It will limit you from creating good stable apps which are easy to maintain and extend. Most of the apps in the current app library are not extendable or maintainable. You need to be able to split the code into small segments to unit test. Otherwise you are taking a step back to pre object orientated test driven development.

  • in Bangle.js
    Avatar for charlie

    yeh if I have time I will make a simplified example and set timeout as you suggest

  • in Bangle.js
    Avatar for charlie

    I have narrowed down what is triggering the low memory (when run from RAM). I have the following class which is basically shifting the queue if push item and over max size:

    export class Queue<T> {
        protected itemLimit:number;
        protected internalArray: Array<T>;
    
        constructor(itemLimit = 3) {
            this.itemLimit = itemLimit;
            this.internalArray = [];
        }
    

    If I initiate 2 or more of these like this:

    this.waypoints = new Queue<IWaypoint>(10);
    this.waterways = new Queue<ILocalisedFeature>(10);
    

    ...the memory bottoms out. Which is curious as even if I comment out the initialisation of the array it still bottoms out.

    The actual non minified compiled typescript looks as follows:

    /***/ './src/constructs/queue.ts': /***/ function (__unused_webpack_module, exports) {
                eval(
                    '\r\nObject.defineProperty(exports, "__esModule", ({ value: true }));\r\nexports.Queue = void 0;\r\nvar Queue = /** @class */ (function () {\r\n    // itemCount = 0;\r\n    function Queue(itemLimit) {\r\n        if (itemLimit === void 0) { itemLimit = 3; }\r\n        var _this = this;\r\n        this.lastN = function (count) {\r\n            if (count === void 0) { count = 2; }\r\n            var newAry = [];\r\n            for (var i = _this.length - 1; i >= Math.max(0, _this.length - count); i--) {\r\n                newAry.push(_this.internalArray[i]);\r\n­            }\r\n            return newAry;\r\n        };\r\n        this.any = function () {\r\n            return _this.length > 0;\r\n        };\r\n        this.lastEntry = function () {\r\n            try {\r\n                return _this.internalArray[_this.length - 1];\r\n            }\r\n            catch (err) {\r\n                return null;\r\n            }\r\n        };\r\n        this.firstEntry = function () {\r\n            return _this.internalArray[0];\r\n        };\r\n        this.lastMinus = function (numberFromEnd) {\r\n            if (numberFromEnd === void 0) { numberFromEnd = 0; }\r\n            return _this.internalArray[_this.length - 1 - numberFromEnd];\r\n        };\r\n        this.clear = function () {\r\n            _this.internalArray.length = 0;\r\n        };\r\n        this.asArray = function () {\r\n            return _this.internalArray;\r\n        };\r\n        this.itemLimit = itemLimit;\r\n        this.internalArray = [];\r\n    }\r\n    Object.defineProperty(Queue.prototype, "length", {\r\n        get: function () {\r\n            return this.internalArray.length;\r\n        },\r\n        enumerable: false,\r\n        configurable: true\r\n    });\r\n    Queue.prototype.isEmpty = function () {\r\n        return !this.any();\r\n    };\r\n    Queue.prototype.push = function () {\r\n        var _a;\r\n        var items = [];\r\n        for (var _i = 0; _i < arguments.length; _i++) {\r\n            items[_i] = arguments[_i];\r\n        }\r\n        var n = (_a = this.internalArray).push.apply(_a, items);\r\n        if (this.itemLimit != null && this.itemLimit > 0) {\r\n            this.internalArray.splice(0, this.length - this.itemLimit);\r\n        }\r\n        return this.length;\r\n    };\r\n    return Queue;\r\n}());\r\nexports.Queue = Queue;\r\n\n\n//# sourceURL=webpack://ck_nav/./src/constru­cts/queue.ts?',
                );
    
                /***/
            },
    

    I am wondering if the get overrides (such as below)

    • which result in Class.prototype stuff is the cause but need to test more.

      get length() {
          return this.internalArray.length;
      }
      
  • in Bangle.js
    Avatar for charlie

    loadRoute is doing two things. Its reading the gpx file with Storage.read, and parsing additional json files with jsonRead. In both cases I am parsing the data into local constructs. The mem used by both these functions is correctly releasing the memory once outside the scope.

    I actually think the memory which is released is memory bangle is using when loading up the main js file on app load.

Actions