RFR: [DRAFT] Support Java literals in @Param annotation

Aleksey Shipilev shade at openjdk.java.net
Tue Nov 30 10:33:22 UTC 2021


On Thu, 9 Sep 2021 16:27:44 GMT, Vsevolod Tolstopyatov <duke at openjdk.java.net> wrote:

> This is a follow-up to https://mail.openjdk.java.net/pipermail/jmh-dev/2020-October/003039.html
> 
> I've prototyped it and found few corners which I'd like to highlight and discuss.
> 
> The initial purpose of the change is to be able to use underscores for the sake of better readability in both code and text reports:
> 
> `@Param("1_000", "10_000", "100_000")` 
> 
> and
> 
> 
> Benchmark        (listSize)   Mode  Cnt      Score   Error  Units
> ShowOff.consume       1_000  thrpt       42294.795          ops/s
> ShowOff.consume      10_000  thrpt        4057.322          ops/s
> ShowOff.consume     100_000  thrpt        2866.069          ops/s
> 
> 
> 
> While doing so, I've decided that it would be nice to support the strict subset of actual Java literals (at least to have a reference to point at) which has a lot of pitfalls:
> 
> * Now we have (?) to support octal, binary and hexadecimal literals
> * The actual grammar is quite wild, so literals like `0_12___3_4` are also supported
> * `l` and `L` at the end of `long` literals are not supported (it seems a bit weird to do so)
> * `NumericLiteralsParser` leaks to public API, so the generated benchmarks can invoke it (not sure what's the API policy here, but it's worth pointing it out)
> * Underscores in floating points literals are not supported, mostly because then I have to match hexadecimal literals with underscores as well. No particular reason apart from "it's extra work without clear benefits". I can implement it if it's required for the PR though.
> 
> Most importantly, support of such literals will break existing benchmarks that prefixed their numeric parameters with zero -- now they are interpreted as octal literals (and either rejected, e.g. `09` or converted to decimal, breaking the original authors intent). Previously, `X.parseX` functions (e.g. `Integer.parseInt`) were used and they are okay with leading zeroes.
> 
> Breaking change seems to be the blocker here, and I'd like to hear your opinion of the acceptable approach aligned with JMH API
> 
> Potential alternatives:
> 
> * Do nothing, don't support underscores
> * Support only decimal literals
> * Support any subset of literals (e.g. decimal and hexadecimal only)
> * Just trim all the underscores and parse it as before via `Integer.parseInt` and so on

Hi, sorry for extremely late reply. This is a tough one compatibility-wise. I think it would be safer to:

- Drop octal literals support, leave only binary, decimal, hexadecimal; they seem to be unambiguous when applied over integral types;
- Move `NumericLiteralsParser` into generated benchmark code to avoid exposure to external code; yes, that would make unit testing much less convenient, you would have to do real JMH tests in `jmh-core-it` to reach the code; and put negative tests in `jmh-core-ct`, so we can check that known-bad values are rejected at compile time;
- Need additional test to verify that `@Param` over `String` does not accidentally converts the values;
- Figure out how hard would it be to support floating-point values, I'd think this one is useful in floating-point benchmarks `HexadecimalFloatingPointLiteral HexSignificand BinaryExponent`

Don't invest much time into this, as we might run into some unknown blocker going forward, which would derail all this.

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

PR: https://git.openjdk.java.net/jmh/pull/50


More information about the jmh-dev mailing list