Constants and static enum variables appear to be instance variables

o A Descriptive Title (i.e. “Simulator Freezes Launching App in Eclipse”)
Constants and static enum variables appear to be instance variables

o The Environment:
Windows 10
Eclipse Neon.1 (4.6.1)

o A detailed description of the issue
Constants and static enum variables appear as instance variables, unexpectedly bloating object sizes.

o Steps to reproduce the issue
Compile and run the test case below. The output will indicate the increase in size shown for various declarations.

o Any applicable additional information
The compiler should be able to create shared instances of variables declared as `const' and `static enum', much like is done for `static const' and `static var' declarations. This should make it more difficult to waste memory accidentally. There could be some unintended side-effects with this change, so this might require a bit of testing to verify.

If this suggestion is rejected, the Programmer's Guide should add documentation for the `static', `const', `enum', and `var' keywords. It should mention that `static' is the only way to get a value that is shared between instances, and that using `static' and `const' together is a good idea to avoid incurring per-instance overhead.

o A code sample that can reproduce the issue (in email only if preferred)

using Toybox.Application;
using Toybox.Lang;
using Toybox.System;
using Toybox.WatchUi;

class ClassWithNothing
{
}

class ClassWithConstValues
{
    const VALUE_0 = 0;
}

class ClassWithStaticConstValues
{
    static const VALUE_0 = 0;
}

class ClassWithStaticValues
{
    static var VALUE_0 = 0;
}

class ClassWithValues
{
    var VALUE_0 = 0;
}

class ClassWithEnumValues
{
    enum {
        VALUE_0
    }
}

class ClassWithStaticEnumValues
{
    static enum {
        VALUE_0
    }
}

var minimum_size;

function get_used_memory() {
    var systemStats = System.getSystemStats();
    return systemStats.usedMemory;
}

function do_test_type(logger, count, type, tname) {
    var array = new [count];

    var prev_used = get_used_memory();

    for (var i = 0; i < count; ++i) {
        array[i] = new type();
    }

    var next_used = get_used_memory();

    var current_size = (next_used - prev_used) / count;
    if (minimum_size == null) {
        minimum_size = current_size;
    }

    logger.debug(Lang.format("$1$: $2$", [ tname, current_size - minimum_size ]));
}

(:test) function test(logger)
{
    do_test_type(logger, 100, ClassWithNothing , " empty class");
    do_test_type(logger, 100, ClassWithStaticConstValues, "static const");
    do_test_type(logger, 100, ClassWithStaticEnumValues , " static enum");
    do_test_type(logger, 100, ClassWithStaticValues , " static var");
    do_test_type(logger, 100, ClassWithConstValues , " const");
    do_test_type(logger, 100, ClassWithEnumValues , " enum");
    do_test_type(logger, 100, ClassWithValues , " var");

    return true;
}

class XApp extends Application.AppBase
{
    function initialize() {
        AppBase.initialize();
    }

    function getInitialView() {
        return [ new WatchUi.View() ];
    }
}

Related: https://forums.garmin.com/showthread.php?367568

  • The following is the output shown by that program on ConnectIQ 2.2.2...

    Shell Version 0.1.0
    ------------------------------------------------------------------------------
    Executing test test...
    DEBUG (21:13): empty class: 0
    DEBUG (21:13): static const: 0
    DEBUG (21:13): static enum: 16
    DEBUG (21:13): static var: 0
    DEBUG (21:13): const: 16
    DEBUG (21:13): enum: 16
    DEBUG (21:13): var: 16
    PASS

    ==============================================================================
    RESULTS
    Test: Status:
    test PASS
    Ran 1 test


    It shows that static const and static var declarations do not add to the size of individual instances, but const, static enum, and enum do.
  • Former Member
    Former Member over 8 years ago
    Hey Travis,

    Thanks again for the test case. I've got it reported and we should be taking a look at it this week.

    -Coleman
  • We have a fix for this, and it looks like it will be part of the 2.3.1 release.
  • I  haven't found this malformation in documentation.

    Is it mean that if I declare

    static const VALUE_0 = 0;

    as a class member  it doesn't consume memory (or only ones not in each occurrence in code)?

    Is the same for global definition?

    Can I declare it by a comma: 

    static const VALUE_0 = 0, VALUE_1 = 2;

    and they all will be static?

    And it means that enum like const like var consume memory, yes?

  • as a class member  it doesn't consume memory (or only ones not in each occurrence in code)?

    Yes.

    Is the same for global definition?

    This is a weird question. There is only one 'global', and it is a module (not a class). Any variable declaration at that scope would get only one copy in memory.

    Can I declare it by a comma: 

    Yes, you can do that. It is equivalent to declaring them separately.

    static const VALUE_0 = 0;
    static const VALUE_1 = 2;

    and they all will be static?

    Yes.

    And it means that enum like const like var consume memory, yes?

    At the time this post was written (several years ago), this was the case. According to the issue was fixed. You should be able to compile and run the test app to see for yourself.

  • I've done some test:

    1. you can put static only into module or class in global is ignored (all globals are "static")

    2. static means: you can access it without instance of class

    3. it doesn't save memory globally but maybe if you have several instances of class there is only one instance of static so it's similar to define global (but because of limitation of globals you have "hide" some globals into class/module)