Re: Exotic classes
Figured out something bizarre about combining lambdas just the other day. Code like static EqualsSupport makeEquals(Set> getters) { EqualsSupport equals = (a, b) -> true; for (var getter : getters) { if (getter instanceof ObjectGetter) { var g = (ObjectGetter) getter; var oldEquals = equals; equals = (a, b) -> oldEquals.apply(a, b) && Object.equals(g.get(a), g.get(b))); } else if (getter instanceof IntGetter) { var g = (IntGetter) getter; var oldEquals = equals; equals = (a, b) -> oldEquals.apply(a, b) && g.get(a) == g.get(b)); } else { // etc... } } return equals; } just doesn't work because the VM thinks it is recursive (it is the same method on the lambda just not the same lambda). So what you need to is use MethodHandles combinators to patch the lambdas together. Oddly, for a sequence of lambdas I've found the loop one works well. -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. To view this discussion on the web, visit https://groups.google.com/d/msgid/mechanical-sympathy/ec9120ca-f3b7-4c9d-90ef-4dacf2e5f810%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
Hi, For a long while, I couldn't think of what to reply with. I just don't feel the problem of grouping fields together deserves to distort the API that much. I guess part of the problem is Java doesn't support a syntax for field references (even though VarHandleDesc are already implemented.) It occurs to me that the hash and equals don't really need VarHandle references. They really just need getters and don't actually need fields. There is no reason you couldn't do a hash and equality on generated "properties." Although you'd have to avoid boxing problems. interface Getter { } interface ObjectGetter { public T get(R record); } interface ValueGetter extends Getter { } interface IntGetter extends Getter { public int get(R record); } private static final Set> GETTERS = Set.of((s) -> sx, (s) -> s.y); private static final EqualsSupport EQUALS = EqualsSupport.of(GETTERS) private static final HashsSupport HASHER = HashSupport.of(GETTERS); private static final Stringer TOSTRING = Stringer.of(GETTERS); // etc.. I think it might be possible to get working without explicit indy static EqualsSupport makeEquals(Set> getters) { EqualsSupport equals = (a, b) -> true; for (var getter : getters) { if (getter instanceof ObjectGetter) { var g = (ObjectGetter) getter; var oldEquals = equals; equals = (a, b) -> oldEquals.apply(a, b) && Object.equals(g.get(a), g.get(b))); } else if (getter instanceof IntGetter) { var g = (IntGetter) getter; var oldEquals = equals; equals = (a, b) -> oldEquals.apply(a, b) && g.get(a) == g.get(b)); } else { // etc... } } return equals; } I'm just not sure this would properly inline everything. But this is starting to get into bikeshedding. Thank you, Steven -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. To view this discussion on the web, visit https://groups.google.com/d/msgid/mechanical-sympathy/4cc49b86-cec6-49a5-a200-2836e026a835%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
> De: "Steven Stewart-Gallus" > À: "mechanical-sympathy" > Envoyé: Samedi 27 Avril 2019 00:15:07 > Objet: Re: Exotic classes > It seems to me you have to do a lot of hacky stuff to get around the "ugly" > API > as you call it. > Maybe it'd be better to separate out the ObjectSupport class into two separate > classes, a HasherSupport class and an EqualsSupport class. > interface HashSupport < T > { > public static < T > HashSupport < T > of ( Lookup lookup , String ... fields > ) { > var mh = createMh ( lookup , fields ); > return ( obj ) -> { > mh . invokeExact ( obj ); > }; > } > int hashCode ( T obj ); > } > and similar for EqualsSupport. One usual issue with people hand writing equals and hashCode is that they doesn't play well together because there are not using the same set of fields, grouping together the implementation of equals and hashCode alleviate this issue. > I feel like ObjectSupport is a bit nebulous and open ended and you'd > inevitably > end up needing more support methods such as a toString method. yes, toString and perhaps compare, but i want to get right equals and hashCode first. Rémi > On Friday, April 26, 2019 at 8:13:17 AM UTC-7, Remi Forax wrote: >>> De: "Steven Stewart-Gallus" < [ javascript-blocked: | >>> stevensele...@gmail.com ] >>> > >>> À: "mechanical-sympathy" < [ javascript-blocked: | >>> mechanica...@googlegroups.com >>> ] > >>> Envoyé: Vendredi 26 Avril 2019 01:51:47 >>> Objet: Re: Exotic classes >> Hi Steven, >> thanks for spending some time on this, >>> 1. Why >>> public abstract class ObjectSupport { >>> public abstract boolean equals ( Object self , Object other ); >>> public abstract int hashCode (); >>> public static ObjectSupport of ( Lookup lookup , String ... fields ) { >>> // impl details >>> } >>> // impl details >>> } >>> and not something like? >>> interface ObjectSupport < T > { >>> public boolean equals ( T self , T other ); >>> public int hashCode ( T obj ); >>> public static < T , U extends ObjectSupport < T >> T of ( Lookup lookup , >>> Class >>> < U > iface , Class < T > obj ) { >>> // impl details >>> } >>> } >>> @Retention ( RetentionPolicy . RUNTIME ) >>> @Target ( ElementType . FIELD ) >>> @interface ObjectSupportField { >>> } >> There are three questions, why not use an interface, why not use generics to >> make the API more typesafe and why not use an annotation to mark the fields, >> (1), it should be an interface, yes : >> (2), yes, the API can be more typesafe, i've implemented that. BTW, the >> correct >> type of equals() if generified is (T, Object), because you can call >> equals(Person, String), it should return false. >> (3),the API you propose can be built on top of the existing one, that's why >> there is an overload of ObjectSupport.of() that takes a function as third >> parameter >> see [ >> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310 >> | >> https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310 >> ] >> so i've updated the code according to (1) and (2). >>> 2. I don't understand why you can't use [ >>> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A- >>> | >>> https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A- >>> ] instead of unsafe. If you can use [ >>> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html >>> | >>> https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html >>> ] things might be easier to optimise because the VM doesn't trust nonstatic >>> final fields but I don't think you'll need to rely on that. >> I need a VM anonymous class otherwise the method handles used to implement >> equals and hashCode are not considered as constant by the JIT. A previous >> version of the API was using one lambdas for equals and one for hashCode, >> but it makes the API ugly. see [ >> https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13 >> | >> https://github.com/fora
Re: Exotic classes
It seems to me you have to do a lot of hacky stuff to get around the "ugly" API as you call it. Maybe it'd be better to separate out the ObjectSupport class into two separate classes, a HasherSupport class and an EqualsSupport class. interface HashSupport { public static HashSupport of(Lookup lookup, String... fields) { var mh = createMh(lookup, fields); return (obj) -> { mh.invokeExact(obj); }; } int hashCode(T obj); } and similar for EqualsSupport. I feel like ObjectSupport is a bit nebulous and open ended and you'd inevitably end up needing more support methods such as a toString method. On Friday, April 26, 2019 at 8:13:17 AM UTC-7, Remi Forax wrote: > > > > -- > > *De: *"Steven Stewart-Gallus" > > *À: *"mechanical-sympathy" > > *Envoyé: *Vendredi 26 Avril 2019 01:51:47 > *Objet: *Re: Exotic classes > > > Hi Steven, > thanks for spending some time on this, > > > 1. Why > publicabstractclassObjectSupport{ > publicabstractboolean equals(Objectself,Object other); > publicabstractint hashCode(); > publicstaticObjectSupport of(Lookup lookup,String... fields){ > // impl details > } > // impl details > } > > and not something like? > interfaceObjectSupport{ > publicboolean equals(T self, T other); > publicint hashCode(T obj); > publicstatic>T of(Lookup lookup,Class > iface,Class obj){ > // impl details > } > } > @Retention(RetentionPolicy.RUNTIME) > @Target(ElementType.FIELD) > @interfaceObjectSupportField{ > } > > > There are three questions, why not use an interface, why not use generics > to make the API more typesafe and why not use an annotation to mark the > fields, > (1), it should be an interface, yes : > (2), yes, the API can be more typesafe, i've implemented that. BTW, the > correct type of equals() if generified is (T, Object), because you can call > equals(Person, String), it should return false. > (3),the API you propose can be built on top of the existing one, that's > why there is an overload of ObjectSupport.of() that takes a function as > third parameter > see > https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310 > > so i've updated the code according to (1) and (2). > > 2. I don't understand why you can't use > https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A- > instead > of unsafe. If you can use > https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html > things > might be easier to optimise because the VM doesn't trust nonstatic final > fields but I don't think you'll need to rely on that. > > > I need a VM anonymous class otherwise the method handles used to implement > equals and hashCode are not considered as constant by the JIT. A previous > version of the API was using one lambdas for equals and one for hashCode, > but it makes the API ugly. see > https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13 > > 3. The raw class file isn't always available at runtime so you can't > necessarily use ObjectSupportImpl as a template. > > > yes, i will inline it (storing it as an array of bytes inside the Java > code) once the API is stable enough. > > 4. > https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180 > Pretty > sure you want a static final field here. You can do that if you're using > ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't > accept arguments so you have to use wonky garbage like a hashmap to pass > runtime data that can't be embedded in a class file easily. > > > No need for static fields there because ObjectSupportImpl is loaded as a > VM anonymous class, so the instance fields are considered as constant if > the object itself is a constant (see the answer to your question 2). > > There is a JMH test if you want to take a look to the generated assembly > code > > https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java > > regards, > Rémi > > -- > You received this message because you are subscribed to the Google Groups > "mechanical-sympathy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to mechanical-sympathy+unsubscr...@googlegroups.com . > For more options, visit https://groups.google.com/d/optout. > > -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
> De: "Steven Stewart-Gallus" > À: "mechanical-sympathy" > Envoyé: Vendredi 26 Avril 2019 01:51:47 > Objet: Re: Exotic classes Hi Steven, thanks for spending some time on this, > 1. Why > public abstract class ObjectSupport { > public abstract boolean equals ( Object self , Object other ); > public abstract int hashCode (); > public static ObjectSupport of ( Lookup lookup , String ... fields ) { > // impl details > } > // impl details > } > and not something like? > interface ObjectSupport < T > { > public boolean equals ( T self , T other ); > public int hashCode ( T obj ); > public static < T , U extends ObjectSupport < T >> T of ( Lookup lookup , > Class > < U > iface , Class < T > obj ) { > // impl details > } > } > @Retention ( RetentionPolicy . RUNTIME ) > @Target ( ElementType . FIELD ) > @interface ObjectSupportField { > } There are three questions, why not use an interface, why not use generics to make the API more typesafe and why not use an annotation to mark the fields, (1), it should be an interface, yes : (2), yes, the API can be more typesafe, i've implemented that. BTW, the correct type of equals() if generified is (T, Object), because you can call equals(Person, String), it should return false. (3),the API you propose can be built on top of the existing one, that's why there is an overload of ObjectSupport.of() that takes a function as third parameter see https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupportTests.java#L310 so i've updated the code according to (1) and (2). > 2. I don't understand why you can't use [ > https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A- > | > https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A- > ] instead of unsafe. If you can use [ > https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html > | > https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html > ] things might be easier to optimise because the VM doesn't trust nonstatic > final fields but I don't think you'll need to rely on that. I need a VM anonymous class otherwise the method handles used to implement equals and hashCode are not considered as constant by the JIT. A previous version of the API was using one lambdas for equals and one for hashCode, but it makes the API ugly. see https://github.com/forax/exotic/commit/168736c43f32520ef6e280db174bf8a848ee4421#diff-0b01bd4ba5740e6b300bfa38e337dd71R13 > 3. The raw class file isn't always available at runtime so you can't > necessarily > use ObjectSupportImpl as a template. yes, i will inline it (storing it as an array of bytes inside the Java code) once the API is stable enough. > 4. [ > https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180 > | > https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180 > ] Pretty sure you want a static final field here. You can do that if you're > using ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't > accept arguments so you have to use wonky garbage like a hashmap to pass > runtime data that can't be embedded in a class file easily. No need for static fields there because ObjectSupportImpl is loaded as a VM anonymous class, so the instance fields are considered as constant if the object itself is a constant (see the answer to your question 2). There is a JMH test if you want to take a look to the generated assembly code [ https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java | https://github.com/forax/exotic/blob/master/src/test/java/com.github.forax.exotic/com/github/forax/exotic/perf/ObjectSupportBenchMark.java ] regards, Rémi > -- > You received this message because you are subscribed to the Google Groups > "mechanical-sympathy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email > to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com | > mechanical-sympathy+unsubscr...@googlegroups.com ] . > For more options, visit [ https://groups.google.com/d/optout | > https://groups.google.com/d/optout ] . -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
1. Why public abstract class ObjectSupport { public abstract boolean equals(Object self, Object other); public abstract int hashCode(); public static ObjectSupport of(Lookup lookup, String... fields) { // impl details } // impl details } and not something like? interface ObjectSupport { public boolean equals(T self, T other); public int hashCode(T obj); public static > T of(Lookup lookup, Class< U> iface, Class obj) { // impl details } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface ObjectSupportField { } 2. I don't understand why you can't use https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/MethodHandles.Lookup.html#defineClass-byte:A- instead of unsafe. If you can use https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html things might be easier to optimise because the VM doesn't trust nonstatic final fields but I don't think you'll need to rely on that. 3. The raw class file isn't always available at runtime so you can't necessarily use ObjectSupportImpl as a template. 4. https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L180 Pretty sure you want a static final field here. You can do that if you're using ObjectSupportImpl as a raw template. Unfortunately defineClass doesn't accept arguments so you have to use wonky garbage like a hashmap to pass runtime data that can't be embedded in a class file easily. -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
> De: "mechanical-sympathy" > À: "mechanical-sympathy" > Envoyé: Mardi 23 Avril 2019 18:23:48 > Objet: Re: Exotic classes > Replies inline > On Monday, April 22, 2019 at 12:37:19 PM UTC-7, Remi Forax wrote: >>> De: "mechanical-sympathy" < [ javascript-blocked: | >>> mechanica...@googlegroups.com ] > >>> À: "mechanical-sympathy" < [ javascript-blocked: | >>> mechanica...@googlegroups.com >>> ] > >>> Envoyé: Lundi 22 Avril 2019 20:25:01 >>> Objet: Re: Exotic classes >>> These classes (especially MostlyConstant) are pretty cool. I have some >>> questions >>> about them: >>> 1. In MostlyConstant I noticed that modifying the constant doesn't call >>> MutableCallSite.syncAll(). Should it? >> yes, you're right from a spec POV i should call syncAll(), >> the thing is that the current OpenJDK implementation doesn't need syncAll, >> but >> it may change in the future or for another implementation. >>> 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem >>> implemented >>> in OpenJDK. Is it correct to call it? >> yes, it's not implemented because the native part of setTarget() do the >> deopt, >> but it's an implementation detail. >>> 3. In my non-scientific JMH measurements, it seems like modifying the call >>> site >>> takes about 1us. Does that sound about right? From what I can tell modifying >>> the constant is akin to deoptimizing the code and recompiling it, which >>> means >>> that 1us seems really fast. >> it's quite fast but it may be because >> - it may be not optimized yet >> - the VM mark all the different generated assembly codes that reference the >> constant as should be removed from the code cache and will do it later, >> - the VM will not re-optimize directly if a code is deoptimized, but jump in >> the >> interpreter and re-optimize later. > I was running this in a JMH benchmark, and I inspected the Assembly and > Compiler > output; I believe it was reaching c2 before swapping. > A followup question: does deoptimization mean it reverts to a C1 copy of the > code, or directly back to the interpreter? i.e. how much work does it have to > undo? no, for a method, the code generated by c1 is often long gone at the time the code generated by c2 detects that it should deopt. And c1 like c2 generates the code optimistically so even if the code generated by c1 was around, there is a good chance it will have to be de-optimized too. BTW, i've just added a way to have equals and hashCode automatically implemented to exotic [1]. Rémi [1] https://github.com/forax/exotic/blob/master/src/main/java/com.github.forax.exotic/com/github/forax/exotic/ObjectSupport.java#L38 >> so there is a good chance that what you are measuring is not all >> de-optimization >> cost. >> Rémi >>> On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote: >>>> Hi all, >>>> i'm preparing a talk at DevoxxFR on how to make a field value, a returned >>>> value, >>>> etc constant for any decent JITs (everything but c1), so i've bundled >>>> together >>>> several patterns i use for implementing dynamic language runtimes into an >>>> Java >>>> API >>>> [ https://github.com/forax/exotic | https://github.com/forax/exotic ] >>>> I would like to have your comments about those exotic classes (it's >>>> already has >>>> been done, it's stupid, it's not thread safe, etc) >>>> regards, >>>> Rémi > -- > You received this message because you are subscribed to the Google Groups > "mechanical-sympathy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email > to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com | > mechanical-sympathy+unsubscr...@googlegroups.com ] . > For more options, visit [ https://groups.google.com/d/optout | > https://groups.google.com/d/optout ] . -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
Replies inline On Monday, April 22, 2019 at 12:37:19 PM UTC-7, Remi Forax wrote: > > > > -- > > *De: *"mechanical-sympathy" > > *À: *"mechanical-sympathy" > > *Envoyé: *Lundi 22 Avril 2019 20:25:01 > *Objet: *Re: Exotic classes > > These classes (especially MostlyConstant) are pretty cool. I have some > questions about them: > 1. In MostlyConstant I noticed that modifying the constant doesn't call > MutableCallSite.syncAll(). Should it? > > > yes, you're right from a spec POV i should call syncAll(), > the thing is that the current OpenJDK implementation doesn't need syncAll, > but it may change in the future or for another implementation. > > > 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem > implemented in OpenJDK. Is it correct to call it? > > > yes, it's not implemented because the native part of setTarget() do the > deopt, but it's an implementation detail. > > > > 3. In my non-scientific JMH measurements, it seems like modifying the > call site takes about 1us. Does that sound about right? From what I can > tell modifying the constant is akin to deoptimizing the code and > recompiling it, which means that 1us seems really fast. > > > it's quite fast but it may be because > - it may be not optimized yet > - the VM mark all the different generated assembly codes that reference > the constant as should be removed from the code cache and will do it later, > - the VM will not re-optimize directly if a code is deoptimized, but jump > in the interpreter and re-optimize later. > I was running this in a JMH benchmark, and I inspected the Assembly and Compiler output; I believe it was reaching c2 before swapping. A followup question: does deoptimization mean it reverts to a C1 copy of the code, or directly back to the interpreter? i.e. how much work does it have to undo? > > so there is a good chance that what you are measuring is not all > de-optimization cost. > > Rémi > > > > On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote: >> >> Hi all, >> i'm preparing a talk at DevoxxFR on how to make a field value, a returned >> value, etc constant for any decent JITs (everything but c1), so i've >> bundled together several patterns i use for implementing dynamic language >> runtimes into an Java API >> >> https://github.com/forax/exotic >> >> I would like to have your comments about those exotic classes (it's >> already has been done, it's stupid, it's not thread safe, etc) >> >> regards, >> Rémi >> >> >> -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
> De: "mechanical-sympathy" > À: "mechanical-sympathy" > Envoyé: Lundi 22 Avril 2019 20:25:01 > Objet: Re: Exotic classes > These classes (especially MostlyConstant) are pretty cool. I have some > questions > about them: > 1. In MostlyConstant I noticed that modifying the constant doesn't call > MutableCallSite.syncAll(). Should it? yes, you're right from a spec POV i should call syncAll(), the thing is that the current OpenJDK implementation doesn't need syncAll, but it may change in the future or for another implementation. > 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem > implemented > in OpenJDK. Is it correct to call it? yes, it's not implemented because the native part of setTarget() do the deopt, but it's an implementation detail. > 3. In my non-scientific JMH measurements, it seems like modifying the call > site > takes about 1us. Does that sound about right? From what I can tell modifying > the constant is akin to deoptimizing the code and recompiling it, which means > that 1us seems really fast. it's quite fast but it may be because - it may be not optimized yet - the VM mark all the different generated assembly codes that reference the constant as should be removed from the code cache and will do it later, - the VM will not re-optimize directly if a code is deoptimized, but jump in the interpreter and re-optimize later. so there is a good chance that what you are measuring is not all de-optimization cost. Rémi > On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote: >> Hi all, >> i'm preparing a talk at DevoxxFR on how to make a field value, a returned >> value, >> etc constant for any decent JITs (everything but c1), so i've bundled >> together >> several patterns i use for implementing dynamic language runtimes into an >> Java >> API >> [ https://github.com/forax/exotic | https://github.com/forax/exotic ] >> I would like to have your comments about those exotic classes (it's already >> has >> been done, it's stupid, it's not thread safe, etc) >> regards, >> Rémi > -- > You received this message because you are subscribed to the Google Groups > "mechanical-sympathy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email > to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com | > mechanical-sympathy+unsubscr...@googlegroups.com ] . > For more options, visit [ https://groups.google.com/d/optout | > https://groups.google.com/d/optout ] . -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
The cost would be a combination of the deopt, cost of slow down, and cost of compilation all of which are variable based on the generated code which embeds the constant and the compiler used. > On 22 Apr 2019, at 20:25, 'Carl Mastrangelo' via mechanical-sympathy > wrote: > > These classes (especially MostlyConstant) are pretty cool. I have some > questions about them: > > 1. In MostlyConstant I noticed that modifying the constant doesn't call > MutableCallSite.syncAll(). Should it? > > 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem > implemented in OpenJDK. Is it correct to call it? > > 3. In my non-scientific JMH measurements, it seems like modifying the call > site takes about 1us. Does that sound about right? From what I can tell > modifying the constant is akin to deoptimizing the code and recompiling it, > which means that 1us seems really fast. > >> On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote: >> Hi all, >> i'm preparing a talk at DevoxxFR on how to make a field value, a returned >> value, etc constant for any decent JITs (everything but c1), so i've bundled >> together several patterns i use for implementing dynamic language runtimes >> into an Java API >> >> https://github.com/forax/exotic >> >> I would like to have your comments about those exotic classes (it's already >> has been done, it's stupid, it's not thread safe, etc) >> >> regards, >> Rémi >> >> >> > > -- > You received this message because you are subscribed to the Google Groups > "mechanical-sympathy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to mechanical-sympathy+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
These classes (especially MostlyConstant) are pretty cool. I have some questions about them: 1. In MostlyConstant I noticed that modifying the constant doesn't call MutableCallSite.syncAll(). Should it? 2. A followup to #1: MutableCallSite.syncAll() doesn't actually seem implemented in OpenJDK. Is it correct to call it? 3. In my non-scientific JMH measurements, it seems like modifying the call site takes about 1us. Does that sound about right? From what I can tell modifying the constant is akin to deoptimizing the code and recompiling it, which means that 1us seems really fast. On Monday, February 26, 2018 at 11:29:19 AM UTC-8, Remi Forax wrote: > > Hi all, > i'm preparing a talk at DevoxxFR on how to make a field value, a returned > value, etc constant for any decent JITs (everything but c1), so i've > bundled together several patterns i use for implementing dynamic language > runtimes into an Java API > > https://github.com/forax/exotic > > I would like to have your comments about those exotic classes (it's > already has been done, it's stupid, it's not thread safe, etc) > > regards, > Rémi > > > > -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
Hi Steven, > De: "Steven Stewart-Gallus" > À: "mechanical-sympathy" > Envoyé: Samedi 19 Janvier 2019 05:19:06 > Objet: Re: Exotic classes > On Friday, January 18, 2019 at 5:37:58 AM UTC-8, Rémi Forax wrote >>> no, CHA only works on class, not on interface. > You're probably know better than me. I seem to remember there's something like > that for interfaces but very limited such as if you ever only have ever one > implementation. You have been prescient :) c2 now does CHA on interfaces. https://bugs.openjdk.java.net/browse/JDK-6986483 [...] Rémi -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
On Friday, January 18, 2019 at 5:37:58 AM UTC-8, Rémi Forax wrote > > no, CHA only works on class, not on interface. > > You're probably know better than me. I seem to remember there's something like that for interfaces but very limited such as if you ever only have ever one implementation. I suppose you could create a class at runtime that fills out an abstract class which implements Supplier. You'd just create a class with a static final field that returns it as an abstract method impl. > It's not the same semantics, you can not change a StableField more than > once so you have the guarantee that once the field is initialized, no > deoptimization can occur. > The other things is the object is not constant, you will get an exception > so it's hard to misuse that API. > The last point is that i expect that at some point i will change the > implementation so the slowpath will cost less than the slowpath of > MostlyConstant, but i've never had the time to think how to do that in a VM > independant way (i know how to do that with Hotspot only). > Probably better just to omit it until you can actually make it behave differently. By the way, how can you get Hotspot to do it? but it means that you have if/else branch for String that the program has > never encounter. > I prefer to not add all the branches statically but add then at runtime > dynamically when i know i need then. > You just have to be extra lazy about it. It's usually bad style but nothing prevents you from doing something like: private static final class Helper { static final Config CONFIG = initConfig(configStr); } private String configStr = null; public static Config getConfig() { return Helper.CONFIG; } private static Config initConfig(String initStr){ // ... } > > > It will not be inlined by the VM :( > Yeah I abandoned trying to make my own ThreadLocalCallSite implementation for now. I couldn't work out many of the details. > > About having a ThreadLocalCallSite, as part of project Loom, we are > discussing about how associate a value to a part of the callstack. > Anyway, the VM doesn't have a code cache per thread, there is only a > global code cache. > It seems like for a lot of things it is just simpler to have separate isolated processes. I wonder if something like Graal could be hacked to have separate separate Java subinterpreters for separate threads. Another option is to clone key classes/methods per core but I wasn't sure about how heavyweight that would be. -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: Exotic classes
> De: "Steven Stewart-Gallus" > À: "mechanical-sympathy" > Envoyé: Jeudi 17 Janvier 2019 07:50:13 > Objet: Re: Exotic classes > I've been working on similar issues trying to optimise something > heavily. I made a similar class to this one (I even had a similar > API) but I found I called it MostlyFinal instead. > private static final MostlyConstant FOO = new MostlyConstant<>(42, > int.class); > private static final IntSupplier FOO_GETTER = FOO.intGetter(); > By the way using a different interface than Supplier can give the JVM > more class hierarchy analysis info and so potentially allow for > inlining even without static final. no, CHA only works on class, not on interface. > You can also simply use a closure in some cases sort of like this: > interface IntBox { >int get(); > } > public IntBox makeBox(int x) { > return () -> x; > } > This is better for inlining because the JVM trusts final fields in VM > anonymous classes more than yours. Unfortunately > TrustStaticFinalFields cannot be a thing by default yet for backwards > compatibility reasons. > I think a lot of these things are pretty neat but unfortunately hard > to package in a generic and usable library because people delving into > these will want to tear into all the internal details for maximum > performance. > I don't really understand your StableField class. How is it supposed > to be any faster than MostlyConstant? It's not the same semantics, you can not change a StableField more than once so you have the guarantee that once the field is initialized, no deoptimization can occur. The other things is the object is not constant, you will get an exception so it's hard to misuse that API. The last point is that i expect that at some point i will change the implementation so the slowpath will cost less than the slowpath of MostlyConstant, but i've never had the time to think how to do that in a VM independant way (i know how to do that with Hotspot only). > I would suggest if you wanted the best speed (in some ways and at a cost of > memory) you could spin a > static final class with a method that returns a constantdynamic entry > and then return a methodhandle to that entry. This seems possibly > heavyweight IMO so I'm still thinking about this myself. better, use a lazy static final field (see [ https://bugs.openjdk.java.net/browse/JDK-8209964), | https://bugs.openjdk.java.net/browse/JDK-8209964), ] i.e. tech javac to either emit a ldc to the ConstantDynamic or do a getfield that will trigger the ConstantDynamic initialization if needed. > If StringSwitchCallSite being a MutableCallSite seems possibly > unneeded with a reworked API to me. but it means that you have if/else branch for String that the program has never encounter. I prefer to not add all the branches statically but add then at runtime dynamically when i know i need then. > I am highly suspicious TypeSwitch will increase performance in most cases. > instanceof checks are highly optimized and give info that allow > further optimizations. It depends, if instanceof else ... is slow if you have deep hierarchy, if the test are not in the right order of occurence and if you have too many branches. But yes, the StringSwitch and the TypeSwitch can be slower/faster than the equivalent cascade of if/else. > You might want to consider using/abusing the JVM's own inline caching > behaviour for interfaces for some dispatching. A MethodHandles.guardWithTest is exactly that ! > It's not too hard to create a bag of interface implementations at > runtime that all dispatch to separate CallSite implementations which > can be faster than exactInvoker/your own MethodHandle lookup logic > sometimes. No, believe me, it's hard. It's the reason i've created (with others) the java.lang.invoke API. > I considered this for a ThreadLocalCallSite class I was > making but I'm still not sure about the design. > So basically one hack to get quicker thread local behaviour is to > subclass Thread and add your own fields/methods like this: > ((MyIface)Thread.currentThread()).doSpecific(); > If you add your own bag of interface implementations then you can do > this dynamically: > MY_IFACE.invokeExact((BagThread)Thread.currentThread()).bag, ...); It will not be inlined by the VM :( About having a ThreadLocalCallSite, as part of project Loom, we are discussing about how associate a value to a part of the callstack. Anyway, the VM doesn't have a code cache per thread, there is only a global code cache. > I'm not sure about the bytecode generation here though. I don't want > to be too blase about that. > It looks like you have some benchmarks setup but I don't see any
Re: Exotic classes
I've been working on similar issues trying to optimise something heavily. I made a similar class to this one (I even had a similar API) but I found I called it MostlyFinal instead. private static final MostlyConstant FOO = new MostlyConstant<>(42, int.class); private static final IntSupplier FOO_GETTER = FOO.intGetter(); By the way using a different interface than Supplier can give the JVM more class hierarchy analysis info and so potentially allow for inlining even without static final. You can also simply use a closure in some cases sort of like this: interface IntBox { int get(); } public IntBox makeBox(int x) { return () -> x; } This is better for inlining because the JVM trusts final fields in VM anonymous classes more than yours. Unfortunately TrustStaticFinalFields cannot be a thing by default yet for backwards compatibility reasons. I think a lot of these things are pretty neat but unfortunately hard to package in a generic and usable library because people delving into these will want to tear into all the internal details for maximum performance. I don't really understand your StableField class. How is it supposed to be any faster than MostlyConstant? I would suggest if you wanted the best speed (in some ways and at a cost of memory) you could spin a static final class with a method that returns a constantdynamic entry and then return a methodhandle to that entry. This seems possibly heavyweight IMO so I'm still thinking about this myself. If StringSwitchCallSite being a MutableCallSite seems possibly unneeded with a reworked API to me. I am highly suspicious TypeSwitch will increase performance in most cases. instanceof checks are highly optimized and give info that allow further optimizations. You might want to consider using/abusing the JVM's own inline caching behaviour for interfaces for some dispatching. It's not too hard to create a bag of interface implementations at runtime that all dispatch to separate CallSite implementations which can be faster than exactInvoker/your own MethodHandle lookup logic sometimes. I considered this for a ThreadLocalCallSite class I was making but I'm still not sure about the design. So basically one hack to get quicker thread local behaviour is to subclass Thread and add your own fields/methods like this: ((MyIface)Thread.currentThread()).doSpecific(); If you add your own bag of interface implementations then you can do this dynamically: MY_IFACE.invokeExact((BagThread)Thread.currentThread()).bag, ...); I'm not sure about the bytecode generation here though. I don't want to be too blase about that. It looks like you have some benchmarks setup but I don't see any txt files with any perf data listed. I mentioned a lot of gibberish earlier but problem my biggest advice would be to add more benchmarks and look at your benchmarks again and also get real world usage data. -- You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group. To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.