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; and if it should be used in NB itself. My post was primarily about whether the JDK could fix the performance issues with Objects.hash(). And that it seems messy to use both Objects.hash() and inlining technique to work around JDK deficiencies that might be fixed in the future.


If optimizing it by storing the hash constant for your Object in a private 
final field improves performance, it certainly is something what can be done. 
(lucene does it where it matters, maven 4 too*). Whenever you compute the 
hashcode over collections of arbitrary size it is something to consider.

But I personally wouldn't do that by default. (measure first and optimize where 
it matters, hashCode() rarely shows up on flame graphs)

I agree and I didn't suggest that it be done by default. I did wonder (in a confusing manner) that in an app if there is a performance problem with collections and the hash, and that it's commonly worked around in large projects, that having an option when the collection is created for hash cache might be handy. I suppose that NB's "generate hash/equals" could have that option, but the developer would still have to subclass the collection to use it. But this might be such an infrequently observed corner case that it's best left up to the app.


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.

-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