was there ever a discussion about trying to avoid ...
# compiler
g
was there ever a discussion about trying to avoid autoboxing in the case where you have a data type like
Copy code
public class DoubleArrayList(): AbstractList<Double> {
  public operator fun get(index: Int): Double //I want the signature (I)D. 
  // I do NOT want the signature (I)Ljava/lang/Double;
}
? I cant help but feel like with all the sophistication of inline classes, kotlins type unification and etc, I could finally have a
List<Double>
that doesnt do an enormous amount of boxing/unboxing. Like, why not generate a function
get()
that's
(I)Lj/l/Double;
and a function
get_$D()
that's
(I)D
, and where the compiler can be certain ahead of time that we're calling DoubleArrayList's
get
, it generates code for`get_$D` instead of
get()
? Again, I know theres a good reason, im just curious. I'm doing some profiling of my app right now, which itself delegates most work to some (fairly recent) fortran code, but it does have some hot loops on the VM, and most are related to poor performance of
Map<String, Double>
and
List<Double>
Some of those are architectural but, it would be nice if i could flip a kind of switch to say "stop using
Double[]
as your backing data types and start using
double[]
" to see how that helps performance
I guess, to answer my own question, reflection becomes tricky
but of course, none of that matters if you're using a generic interface. you'll have to define and use a specialized class in order to call any specialized functions, and at that point
"stop using
Double[]
as your backing types and start using `double[]`"
you can do that yourself
or wait for Java's Project Valhalla
g
ahhh so its already attempting to do this, it was just my own testing that was flawed?
so my reading of these issues is that in the sample code I give, the generated code should be calling the specialized method?
i was using an intelliJ plugin to "view byte code", perhalps it wasnt actually showing me what was coming out of my build pipeline?
e
it will try do do so in some cases, but there's many where it can't, and some where it's missing
your case here falls partly falls into KT-19038 (so it doesn't create the primitive-specialized functions for returning), and even if it did, KT-18906 means it won't be practically useful for List<Double> anyway
if you want to avoid boxing, for now you will need to avoid using the generic interface at all, e.g.
Copy code
class DoubleArrayList /* no mention of List<Double> at all */ {
    operator fun get(index: Int): Double // etc.
}
j
eclipse collections supports this sort of as a successor to trove as a placeholder
e
yes, those already exist. or, if you can put a maximum bound on the size, you can use Java NIO buffers. or, if your dimensions never change, then primitive arrays directly
j
those might act less like arraylists than native collections offer.
i presume that being specific about using List is going to buy some accounting for removal and size counting that flat memory isn't offering
e
nio.buffer has position/limit/capacity as well as allowing absolute access, so if the maximum capacity is known, position/limit can be used to simulate a growing primitive collection. although of course you could diy with array[capacity] + var size
j
at whatever point you decide to use an array to do the job of a list you are going to have to track the gaps manually or do a bunch of fun memcp. porting Rope<Double> from java to kotlin using DoubleArray is likely to be more useful than an ArrayList abstraction for 8 byte values.