GithubHelp home page GithubHelp logo

Comments (9)

benjamin-bader avatar benjamin-bader commented on September 28, 2024 1

My understanding is that the ~1.5kb "memory penalty" for enums happens per declaration

Hmm, maybe I misunderstand. I'm thinking that quite a bit of that 1kb comes from the base class and associated code, which (thanks to object orientation) are shared across declarations. Certainly, methods like Enum#values() get deduplicated during dexing.

As you say, it's not exactly the case that using a few enums will ruin your app. I still hold the belief that the safety provided by enums outweighs their cost on-device. I certainly wouldn't use such a feature as int-enums myself, but wouldn't say no to having an option (non-default) to generate them.

from thrifty.

futtetennista avatar futtetennista commented on September 28, 2024 1

I'm not working on a project that involves Thrift on Android atm so I won't
be able to try it in the near future. But thanks a lot for implementing it.

On Fri, 11 Nov 2016, 02:15 Ben Bader, [email protected] wrote:

@futtetennista https://github.com/futtetennista I don't know if you're
still interested in this feature, but I slapped it together just now. It's
available to play with at
https://github.com/benjamin-bader/thrifty/tree/int-enums. I'm probably
not going to publish this as a snapshot soon; it's such a far-reaching
change that the current test setup can't do both Java and IntDef enums.

If you do try this out, I'd be curious what it does to your total method
count and to your .dex size. My suspicion is that it won't do much, due to
the helper classes. If we decided to forego string names, that would change
things considerably.


You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub
#20 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AATuwz8hwtw1i6xq_9PrGZzQ6HTUKKGZks5q88GogaJpZM4H1Ds2
.

from thrifty.

benjamin-bader avatar benjamin-bader commented on September 28, 2024

I've always thought that video's argument to be a bit of a strawman. The overhead of enums looks bad only compared to an impossibly-tiny dex binary. Additionally, that huge 1kb hit only really applies to the first enum you add; the bulk of the added code in your .dex is shared across all other enum classes. In any event, in practice your actual code (to say nothing of the libraries you use) will utterly dwarf the size of code dedicated to enums.

Ints help you avoid that overhead, but at what cost? If you just use ints in an ad-hoc fashion, you lose all semblance of type-safety. To regain some measure of sanity, you must:

  • Find an appropriately-named class to host your ints (extra overhead of a non-instantiated class)
  • Declare a custom @IntDef annotation, e.g. @NotAnEnum
  • Use @NotAnEnum everywhere such an int occurs

My opinion (and it is an opinion) is that the extra few kb of memory is a small price to pay for safer, more readable code. You might argue that, as a library, thrifty doesn't (or shouldn't) have the luxury of deciding how much memory it should be able to use. That's a valid point, but I'd argue that thrifty is already quite opinionated, and its opinions impose a burden on consumers. Pervasive use of builders, for example, doubles the generated method count as well as bulking up the size of the .dex file - in the name of increased safety.

TL;DR: I'd vote 'no' on this one, but if one were to feel strongly I wouldn't say no to a patch - so long as it were off by default (i.e. regular enums would still be generated unless an --int-enums flag were given)

from thrifty.

futtetennista avatar futtetennista commented on September 28, 2024

The topic always puzzled me I must admit and by reading posts and comments around the internet it looks like using or not using enums should be evaluated on a per-app basis and that there is no bullet-proof solution. I'm a big fan of enums and type-safety myself so I totally agree with you on that. On the other hand I'd be curious to see if there are any substantial improvements by not using enums in our app, since we use enums extensively. I might spike this if I find some free time.

Could you elaborate on:

Additionally, that huge 1kb hit only really applies to the first enum you add; the bulk of the added code in your .dex is shared across all other enum classes.

My understanding is that the ~1.5kb "memory penalty" for enums happens per declaration (but again that doesn't mean that your apk size will explode just because your using a bunch of enums).

from thrifty.

benjamin-bader avatar benjamin-bader commented on September 28, 2024

I finally have some space in my schedule to look in to this. It is certainly doable.

One feature of enums that I treasure is the name() method - so very useful for logging! Also a prerequisite for any textual Protocol (such as the current SimpleJsonProtocol). We will need a method to get a name from an int-enum.

Another question on my mind is how all of this should be organized. Most current uses of int-enums naturally live within e.g. a Layout or a Service; we would be generating domain values. It would be confusing (to me, at least) to make up some generic IntEnums class to hold disparate Thrift enumeration values.

In light of this, I'm considering the following unorthodox API design - any feedback would be most welcome:

Thrift:

enum Foo {
  BAR = 1,
  BAZ = 2,
  QUUX = 3
}
@IntDef({Foo.BAR, Foo.BAZ, Foo.QUUX})
@Retention(SOURCE)
@Target({PARAMETER, METHOD, LOCAL_VARIABLE})
public @interface Foo {
  int BAR = 1;
  int BAZ = 2;
  int QUUX = 3;

  // If only we had Java 8 on Android and default interface methods!
  final class Helper {
    private Helper() {
      // no instances
    }

    public static String nameOf(@Foo int value) {
      switch (value) {
        case Foo.BAR: return "BAR";
        case Foo.BAZ: return "BAZ";
        case Foo.QUUX: return "QUUX";
        default: return null;
      }
    }
  }
}

Things to like:

  • It's lightweight relative to actual enums
  • The end-user "API" is quite familiar, i.e. "TypeName"."MEMBER_NAME"
  • Self-contained

Things not to like:

  • Interface-constants antipattern, now in @interface flavor
  • Helper is painful: Foo.Helper.nameOf(Foo.BAR)
  • The extra Helper classes eat up quite a bit of the savings compared to plain enums

The last point in particular worries me. An alternative to helper-per-int-enum might be to consolidate all enum helper-methods in a package into one class, e.g. com.foo.bar.EnumHelper, with methods like public static String nameOfFoo(@Foo int value). Definitely not at all a fan of this API, but it would minimize the bloat.

The above design is my best thought for the moment, but depending on the costs incurred I'm not sure that it is worth implementing. Thoughts?

from thrifty.

benjamin-bader avatar benjamin-bader commented on September 28, 2024

As a reminder to myself, this design is blocked pending the next release of JavaPoet - square/javapoet/issues/467 is fixed in master, but not shipped, so no fields in annotations at present.

from thrifty.

benjamin-bader avatar benjamin-bader commented on September 28, 2024

Today's release of JavaPoet 1.8 finally includes the bugfixes needed to move this forward.

The next step is to just try it and see what happens!

from thrifty.

benjamin-bader avatar benjamin-bader commented on September 28, 2024

@futtetennista I don't know if you're still interested in this feature, but I slapped it together just now. It's available to play with at https://github.com/benjamin-bader/thrifty/tree/int-enums. I'm probably not going to publish this as a snapshot soon; it's such a far-reaching change that the current test setup can't do both Java and IntDef enums.

If you do try this out, I'd be curious what it does to your total method count and to your .dex size. My suspicion is that it won't do much, due to the helper classes. If we decided to forego string names, that would change things considerably.

from thrifty.

benjamin-bader avatar benjamin-bader commented on September 28, 2024

I don't think this will ever land - absent any user interest, I'm personally not inclined to either adopt or maintain this feature.

from thrifty.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.