RFR: 8300184: Optimize ResourceHashtableBase::iterate_all using _number_of_entries [v2]

Xin Liu xliu at openjdk.org
Mon Jan 16 23:24:23 UTC 2023


> Current implementation needs to visit all buckets. In extreme case, an empty hashtable with 1k buckets. iterate_all() loads 1k buckets for nothing. `_number_of_entries` is the number of nodes in the hashtable. This patch leverages that to quit iteration earlier. The real effect is up to the distribution of nodes among buckets.
> 
> I also included a debug log in the original patch. It was used for the observation in the following section, but I deleted it because it introduces circular dependency. 
> 
> log_debug(hashtables)("ResourceHashtableBase table_size = %d, break at " INTX_FORMAT, sz, (bucket - table()));
> 
> **Evaluation** 
> In release build, the patch is very marginal. class loading do use ResourceHashtable but they are saturated. 
> 
> I use it to run `Renaissance/finagle-http`. hahstable iterate_all quits a little bit earlier and save some loads. eg. in line 2, there are 109 buckets in the hashable. the iteration quit at 68th bucket, we save 42 loads. 
> 
> 
> $java -Xlog:hashtables=debug  -jar renaissance-gpl-0.14.1.jar finagle-http
> ...
> [12.824s][debug][hashtables] table_size = 109, break at 109
> [12.824s][debug][hashtables] table_size = 109, break at 68
> [12.824s][debug][hashtables] table_size = 109, break at 107
> [12.825s][debug][hashtables] table_size = 109, break at 108
> [12.825s][debug][hashtables] table_size = 109, break at 99
> [12.825s][debug][hashtables] table_size = 109, break at 108
> [12.825s][debug][hashtables] table_size = 109, break at 98
> [12.825s][debug][hashtables] table_size = 109, break at 109
> [12.825s][debug][hashtables] table_size = 109, break at 102
> ...
> 
> 
> Another application is in AsyncLog Thread. We have a hashtable with 17 buckets. Each Log Output creates one node in the hashtable. In common cases, there are only 2~3 nodes in the hashtable. Each time AsyncLog Thread flushes the buffer, it has to scan the hashtable twice. Saving loads means saving the memory bandwidth for the application. 
> 
> In fastdebug build, extra verification is deployed. It's common to observe that JVM scan an empty hashtable. It's in destroy_VM. 
>  
> 
> ./build/linux-x86_64-server-fastdebug/images/jdk/bin/java -Xlog:hashtables=debug --version
> openjdk 21-internal 2023-09-19
> OpenJDK Runtime Environment (fastdebug build 21-internal-adhoc.xxinliu.jdk)
> OpenJDK 64-Bit Server VM (fastdebug build 21-internal-adhoc.xxinliu.jdk, mixed mode, sharing)
> [0.130s][debug][hashtables] table_size = 139, break at 0
> [0.136s][debug][hashtables] table_size = 107, break at 0
> [0.136s][debug][hashtables] table_size = 1009, break at 0
> [0.136s][debug][hashtables] table_size = 109, break at 107
> [0.136s][debug][hashtables] table_size = 109, break at 109
> [0.137s][debug][hashtables] table_size = 109, break at 101

Xin Liu has updated the pull request incrementally with two additional commits since the last revision:

 - Remove log_debug.
   
   Thread::name() isn't safe in gtest. We don't need the log line.
 - Fixed the build error on x86-32.

-------------

Changes:
  - all: https://git.openjdk.org/jdk/pull/12016/files
  - new: https://git.openjdk.org/jdk/pull/12016/files/93533a64..00a8abb5

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=12016&range=01
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=12016&range=00-01

  Stats: 9 lines in 1 file changed: 0 ins; 8 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/12016.diff
  Fetch: git fetch https://git.openjdk.org/jdk pull/12016/head:pull/12016

PR: https://git.openjdk.org/jdk/pull/12016


More information about the hotspot-dev mailing list