Fast lazy properties


#1

Currently there is no fast and nice way to handle lazy evaluated properties in Kotlin. I know about delegated properties and the standard delegate function “lazy”. But the problem with this implementation is; that it is memory consuming, somewhat slow, and ugly when you want to use another ThreadSafteyMode.

I would like to have a nice way to handle lazy properties. I’m currently making an AST tree that is loosely based on the Roslyn architecture. See https://blogs.msdn.microsoft.com/ericlippert/2012/06/08/persistence-facades-and-roslyns-red-green-trees/ Especially the bit about the red tree is relevant.

My proposal is to introduce the following possibility in the language:

Instead of

val myProperty : DummyClass by lazy(LazyThreadSafetyMode.NONE) {
     // create DummyClass...
}

I would like the following option:

val myProperty : DummyClass
   load() {
      return DummyClass()
   }

or shorter

val myProperty : DummyClass
   load() = DummyClass()

or a little bit different:

val myProperty : DummyClass
  load() {
      field = DummyClass()
  }

The generated code for load could be very efficient, because there is no need for an extra null check after initilization, and also no need for extra instances.

The synchronized version would look like this:

val myProperty : DummyClass
   load() {
       return synchronized(this) {
             if (field !== null) {
                 DummyClass()
             }
       }
  }

or this

val myProperty : DummyClass
   load() {
       synchronized(this) {
             if (field !== null) {
                 field = DummyClass()
             }
       }
  }

Load should only be available for “val” and not for “var” properties.


#2

This is the first time I’ve heard of lazy being slow. What exactly do you mean? If you’re talking about object creation–have you measured it? There’s a lot of misconceptions when it comes to the JVM and performance (like the misconception that object allocation/deallocation is always bad).

The effect of an extra null check and extra instances on performance could in some cases be zero. Maybe someone who knows the JVM better could shed some light on the subject?


#3

This is the first time I’ve heard of lazy being slow. What exactly do you mean? If you’re talking about object creation–have you measured it?

I should have said that the implementation is not the most efficiënt. I haven’t measured it, so i shouldn’t say it’s slow. In almost all use cases the performance is probably alright.

The problem in my case is that i have an AST tree that is created lazily with potentially millions of objects. The creation of these objects is not computationally expensive, so a little bit off overhead could be noticed.


#4

You should provide something to work with. I’ve recently optimized performance for some heavy duty code with lazy initialization and did not found problems with lazy delegate with either processor performance or memory.

If you have some kind of specific problem, you can create your own delegate. That is the beauty of delegate solution, it is not the part of the language, but just a library function. Introducing new language feature for that is in my opinion completely out of the question.


#5

Apart from possible misconceptions on object allocation performance, what kind of optimization can be done about lazy? Remember that everything Kotlin/JVM compiles eventually boils down into JVM bytecode. Is there any more efficient code you can write in Java, regardless of how ugly the syntax looks, that could produce more efficient results? (not sure about K/JS and K/N)


#6

Hi hope this can help you.

This is a single variable (mixing lock and lazy instance) synchronized lazy without volatile field suitable for JVM 9+.
The above implementation is generally faster than you proposed one, but is possible to avoid the instanceOf operator using a explicit lock value (as lazy does).


#7

But there does not seem to be a faster version for LazyThreadSafetyMode.NONE as in the OP.


#8

Yes, you are right.

My example is thread safe as yours, LazyThreadSafetyMode.NONE is not thread safe.

Write a not thread-safe lazy initialization is really trivial! (You have to remove the synchoniezed in you example)


#9

InstanceOf should be almost free on Java 6+, so actual performance still should be measure.