On Fri, 5 Aug 2022 16:12:08 GMT, Jan Lahoda <jlah...@openjdk.org> wrote:

> The pattern matching switches are using a bootstrap method 
> `SwitchBootstrap.typeSwitch` to implement the jumps in the switch. Basically, 
> for a switch like:
> 
> switch (obj) {
>     case String s when s.isEmpty() -> {}
>     case String s -> {}
>     case CharSequence cs -> {}
>     ...
> }
> 
> 
> this method will produce a MethodHandle that will be analyze the provided 
> selector value (`obj` in the example), and will return the case index to 
> which the switch should jump. This method also accepts a (re)start index for 
> the search, which is used to handle guards. For example, if the `s.isEmpty()` 
> guard in the above sample returns false, the matching is restarted on the 
> next case.
> 
> The current implementation is fairly slow, it basically goes through the 
> labels in a loop. The proposal here is to replace that with a MethodHandle 
> structure like this:
> 
> obj == null ? -1
>                   : switch (restartIndex) {
>                         case 0 -> obj instanceof String ? 0 : obj instanceof 
> CharSequence ? 2 : ... ;
>                         case 1 -> obj instanceof String ? 1 : obj instanceof 
> CharSequence ? 2 : ... ;
>                         case 2 -> obj instanceof CharSequence ? 2 : ... ;
>                         ...
>                         default -> <labels-count>;
>                     }
> 
> 
> This appear to run faster than the current implementation, using testcase 
> similar to the one used for https://github.com/openjdk/jdk/pull/9746 , these 
> are the results
> 
> PatternsOptimizationTest.testLegacyIndyLongSwitch   thrpt   25   1515989.562 
> ± 32047.918  ops/s
> PatternsOptimizationTest.testHandleIndyLongSwitch   thrpt   25   2630707.585 
> ± 37202.210  ops/s
> 
> PatternsOptimizationTest.testLegacyIndyShortSwitch  thrpt   25   6789310.900 
> ± 61921.636  ops/s
> PatternsOptimizationTest.testHandleIndyShortSwitch  thrpt   25  10771729.464 
> ± 69607.467  ops/s
> 
> 
> The "LegacyIndy" is the current implementation, "HandleIndy" is the one 
> proposed here. The translation in javac used is the one from #9746 in all 
> cases.

> Would it be possible to add a special case where the labels are all the same 
> type? Like all labels are Class.class or Object.class? While testing out the 
> pattern matching, I've found myself doing the following
> 
> ```java
> switch (o) {
>     case Class<?> c when c == Object.class -> {}
>     case Class<?> c when c == Integer.class -> {}
>     case Class<?> c when c == String.class -> {}
>     case Class<?> c when c == Double.class -> {}
>     // ...
> }
> ```

I think that there may eventually be some improvements, although the current 
round of patches is not intended to improve this pattern, sorry. Also, I would 
not expect better behavior that a sequence of ifs.

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

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

Reply via email to