On 11/10/25 19:25, Ernie Rael wrote:
> On 25/11/10 9:28 AM, Michael Bien wrote:
>> On 11/10/25 17:26, Ernie Rael wrote:
>>> On 25/11/08 4:13 PM, Michael Bien wrote:
>>>> I ran a little JMH benchmark since this made me curious.
>>>>
>>>> https://gist.github.com/mbien/8f029092749c590878b9b83b8e79fe53
>>>>
>>>> The JVM seems to have some problems to unroll the Objects.hash() method.
>>>> Even though It is the least verbose approach, it also makes me less 
>>>> enthusiastic to switch to it given that
>>>> it would be a "generate and forget" situation in both cases where I am not 
>>>> worried about a few lines more.
>>> Should this be filed as a problem with the compiler/hot-spot and/or 
>>> Objects.hash() method?  Do you believe that this performance issue can not 
>>> be addressed in the JDK?
>>>
>>> Seems a shame to have multiple ways to do something dependent on how the 
>>> result is cached, which could change; but it does seems unlikely that if 
>>> some result is cached, that in the future it will no longer cached.
>> not sure I follow. The dev who implements the hash method has control over 
>> how it is computed and when it is computed. Hash could be as simple as an 
>> UID and nothing needs to be computed. E.g hash code for Integer 5 is 5 which 
>> is a pretty good UID for 5.
>
> IIUC, the discussion is if NB should use Objects.hash() when it generates 
> code, instead of inlining;

I wouldn't mind to use Objects.hash() as (new) default for NB's code gen and 
keep the unrolled version as option somewhere in the settings.

>>
>> also: don't read too much into the small benchmark I quickly wrote out of 
>> curiosity
>
> It seemed like the benchmark was/is swaying your thinking. Be nice if it 
> could be fixed in the JDK. 

its just a data point for me.


The JDK team is working on several jeps which would make inlining calls like 
this for the JVM easier in future.

https://openjdk.org/jeps/500
https://openjdk.org/jeps/526
and of course the whole project valhalla

meanwhile: use records where it makes sense

-mbien



>
> -ernie
>
>>
>> best regards,
>>
>> michael
>>
>>
>> * https://github.com/apache/maven/issues/2481
>>
>>
>>>   I don't suppose there's a marketing coup to be had against Eclipse and 
>>> Intellij over this issue.
>>>
>>> IIUC, the hash is used in lookup for many collection types. If the JDK 
>>> can't fix Objects.hash() performance, I wonder if collection creation 
>>> could/should have a cache-hash option to force the performance/size 
>>> tradeoff.
>>>
>>> -ernie
>>>
>>>
>>>> But when the hash value is cached -> I would probably use the most compact 
>>>> way to compute it.
>>>>
>>>> and/or use records of course
>>>>
>>>> (maven 4 made recently some efforts to cache hash constants since not 
>>>> re-computing them made a
>>>> measurable difference there - esp when the tree involved collections)
>>>>
>>>> best regards,
>>>> michael
>>>>
>>>> On 11/5/25 23:00, Michael Bien wrote:
>>>>> Hi,
>>>>>
>>>>> The hashCode method generator most likely didn't get updated to use the 
>>>>> Objects.* utility and does the computation "by hand".
>>>>>
>>>>> I think this came up on slack before and it would be nice if it could be 
>>>>> updated to use Objects.hash(...) but nobody got to it so far.
>>>>>
>>>>> JDK uses a "n = 31*n + obj.hashCode()" loop, NB does the same, just with 
>>>>> a different prime / start offset and unrolls the loop.
>>>>>
>>>>> regarding equals: Double.compare() would use Double.doubleToLongBits() 
>>>>> internally and might be easier to read - something
>>>>> NB could change too but its probably not that important.
>>>>>
>>>>> best regards,
>>>>> michael
>>>>>
>>>>>
>>>>> On 11/5/25 22:20, Kenneth Fogel wrote:
>>>>>> For a discussion for Java Beans in my writing, I generated the hashCode 
>>>>>> and equals methods in NetBeans. I then generated the same methods with 
>>>>>> Eclipse and Intellij.  It is the hashCode and equals methods that stood 
>>>>>> out as Eclipse and Intellij generate the exact same code that is quite 
>>>>>> different from NetBeans.
>>>>>>
>>>>>> NetBeans:
>>>>>>       @Override
>>>>>>       public int hashCode() {
>>>>>>           int hash = 3;
>>>>>>           hash = 97 * hash + Objects.hashCode(this.title);
>>>>>>           hash = 97 * hash + Objects.hashCode(this.author);
>>>>>>           hash = 97 * hash + Objects.hashCode(this.publisher);
>>>>>>           hash = 97 * hash + Objects.hashCode(this.isbn);
>>>>>>           hash = 97 * hash + this.pages;
>>>>>>           hash = 97 * hash + this.copiesInStock;
>>>>>>           hash = 97 * hash + this.copiesSold;
>>>>>>           hash = 97 * hash + (int) 
>>>>>> (Double.doubleToLongBits(this.wholesaleCost) ^ 
>>>>>> (Double.doubleToLongBits(this.wholesaleCost) >>> 32));
>>>>>>           hash = 97 * hash + (int) 
>>>>>> (Double.doubleToLongBits(this.retailPrice) ^ 
>>>>>> (Double.doubleToLongBits(this.retailPrice) >>> 32));
>>>>>>           hash = 97 * hash + (this.suitableForChildren ? 1 : 0);
>>>>>>           return hash;
>>>>>>       }
>>>>>>
>>>>>> Eclipse and IntelliJ:
>>>>>>       @Override
>>>>>>       public int hashCode() {
>>>>>>           return Objects.hash(title, author, publisher, isbn, pages, 
>>>>>> copiesInStock, copiesSold, wholesaleCost, retailPrice, 
>>>>>> suitableForChildren);
>>>>>>       }
>>>>>>
>>>>>> In NetBeans, why is the initial hash value 3 and then 97 that is always 
>>>>>> added? Is the fact that 97 + 3 = 100 significant? From the perspective 
>>>>>> of explaining what this code does, the Eclipse/IntelliJ version is much 
>>>>>> simpler to describe.
>>>>>>
>>>>>> Is there a reason for the additional code in the NetBeans version. Is 
>>>>>> the NetBeans version less prone to false positives, meaning you need to 
>>>>>> use equals() less often?
>>>>>>
>>>>>> For the equals() method the difference is also interesting.
>>>>>>
>>>>>> NetBeans
>>>>>>       @Override
>>>>>>       public boolean equals(Object obj) {
>>>>>>           if (this == obj) {
>>>>>>               return true;
>>>>>>           }
>>>>>>           if (obj == null) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (getClass() != obj.getClass()) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           final BookBean other = (BookBean) obj;
>>>>>>           if (this.pages != other.pages) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (this.copiesInStock != other.copiesInStock) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (this.copiesSold != other.copiesSold) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (Double.doubleToLongBits(this.wholesaleCost) != 
>>>>>> Double.doubleToLongBits(other.wholesaleCost)) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (Double.doubleToLongBits(this.retailPrice) != 
>>>>>> Double.doubleToLongBits(other.retailPrice)) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (this.suitableForChildren != other.suitableForChildren) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (!Objects.equals(this.title, other.title)) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (!Objects.equals(this.author, other.author)) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           if (!Objects.equals(this.publisher, other.publisher)) {
>>>>>>               return false;
>>>>>>           }
>>>>>>           return Objects.equals(this.isbn, other.isbn);
>>>>>>       }
>>>>>>
>>>>>> Eclipse and IntelliJ
>>>>>>       @Override
>>>>>>       public boolean equals(Object o) {
>>>>>>           if (o == null || getClass() != o.getClass()) return false;
>>>>>>           BookBean bookBean = (BookBean) o;
>>>>>>           return pages == bookBean.pages && copiesInStock == 
>>>>>> bookBean.copiesInStock && copiesSold == bookBean.copiesSold && 
>>>>>> Double.compare(wholesaleCost, bookBean.wholesaleCost) == 0 && 
>>>>>> Double.compare(retailPrice, bookBean.retailPrice) == 0 && 
>>>>>> suitableForChildren == bookBean.suitableForChildren && 
>>>>>> Objects.equals(title, bookBean.title) && Objects.equals(author, 
>>>>>> bookBean.author) && Objects.equals(publisher, bookBean.publisher) && 
>>>>>> Objects.equals(isbn, bookBean.isbn);
>>>>>>       }
>>>>>>
>>>>>> In this code Eclipse and IntelliJ use Double.compare for comparing 
>>>>>> fields that are doubles while NetBeans uses Double.doubleToLongBits.
>>>>>>
>>>>>> Is this even something to worry about? I am not advocating for this code 
>>>>>> to be the same in all three IDEs. I would like to know if the 
>>>>>> differences are significant. From what I see and from my limited 
>>>>>> understanding about how this code performs, I’d guess the 
>>>>>> IntelliJ/Eclipse code is superior.
>>>>>>
>>>>>> Ken
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [email protected]
>>>> For additional commands, e-mail: [email protected]
>>>>
>>>> For further information about the NetBeans mailing lists, visit:
>>>> https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists
>>>>
>>>>
>>>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists



Reply via email to