Some followup on this:

Whether you pass in Closure or interface does not matter - Groovy (as of 2.4.5) 
generates the same (poor) code to set the fields. In the SAM coercion case, it 
actually creates a closure first then creates the SAM instance from it, it 
doesn't directly make the closure be a subclass. I also discovered that static 
compiler can implicitly coerce Closure to interface type but NOT abstract class 
of single abstract method.

As far as I can tell, there is no way to work around this situation, so I will 
have modify all of my classes in this framework to remove "private" from their 
fields, so they have real getters and setters, then CompileStatic will bind to 
those. At least that is a very easy and safe change to make in a lot of files 
very quickly. I still wish there was an easy way to cache the closures (it's 
not trivial for me here because I have closures inside of closures, so even if 
I cache the top-level closure, the inner closures will get recreated).

Jason

From: Winnebeck, Jason [mailto:[email protected]]
Sent: Monday, December 07, 2015 12:13 PM
To: [email protected]
Subject: CompileStatic closure accessing "this object" private variable via 
setGroovyObjectProperty

I have code with performance issues using closures accessing private fields:

@CompileStatic
class X {
  private Y a,b,c

  void blah() {
    doClosureThing { //This gets run in a loop, 1000s of times
       a = ...
       b = ...
       c = ...
}}}

When profiling, I see the majority of time is spent in 
ScriptBytecodeAdapter.setGroovyObjectProperty. Looking at the bytecode, I see 
the closure is setting X variables a,b,c via this method, which essentially 
delegates to a reflection-based set: "getThisObject().setProperty("a", value)". 
I notice that the read references to a, b, c use a generated method like 
"pfaccess$1" to actually read the values.

Is this expected behavior for static compiler?

If I create setters for the fields, the closure bytecode references the setters 
directly (although there is an awkward ScriptBytecodeAdapter.castToType of 
getThisObject instead of a normal cast), and the speedup is about 10x for my 
code (70ms to 6ms).

This is in performance-sensitive code and we use this pattern in a lot of 
classes to execute small pieces of business logic on 1000s+ items. Any 
recommendations on how to improve without requiring changes other than in the 
shared doClosureThing method? One thing I am about to try is changing my 
methods like doClosureThing from a Closure to an abstract class, trying to 
replicate the behavior I get with delegates by manually creating non-abstract 
methods that delegate to the original closure's delegate, but it is a lot of 
work and I'm not even sure if it will do anything.

Jason Winnebeck
Software Engineer III Contractor - IT Software Development | Windstream
600 Willowbrook Office Park, Rochester, NY 14450
[email protected]<mailto:[email protected]> | 
windstreambusiness.com
o: 585.794-4585

________________________________
This email message and any attachments are for the sole use of the intended 
recipient(s). Any unauthorized review, use, disclosure or distribution is 
prohibited. If you are not the intended recipient, please contact the sender by 
reply email and destroy all copies of the original message and any attachments.

Reply via email to