Wednesday, 23 November 2016

JCStress Framework

JCStress is one of the openJDK test frameworks. It is designed to validate Java Memory Model (JMM) requirements on JVM.

Latest release supports only Java9 but older updates also works with java8. The API is very simple and it is annotation based.
To get java8 version you have to clone mercurial repository and update it to older release:

hg clone http://hg.openjdk.java.net/code-tools/jcstress/
hg up 223:bda9fbee58c8
mvn clean install

The main annotations are:

@JCStressTest - Class with test
@State - Class with test state (in most cases the same class as  @JCStressTest)
    State class requires non argument constructor
@Outcome - Validates test results. Following arguments are allowed:
  • id - expected results e.g. for IntResults2 "[1, 0]"
  • expect - Expct enum values most common Expect.ACCEPTABLE or Expect.FORBIDDEN
  • desc - result description
@Description - describe text content

Inside test class you can select methods to be executed by thread with @Actor
If you require results after all threads have finished you can use @Arbiter on method. This method will be executed after all @Actor methods
The results are collected by classes annotated with @Result which are passed as arguments to @Actor methods or @Arbiter methods.
There are number of predefined @Result classes e.g. BooleanResult1, IntResult3, DoubleResult1, StringResult1.

Now it is time to write first test. It is an example of StoreLoad reordering on modern cpus (lack of proper synchronization is intentional).

-- --
You can download git project JMMPresentation and build it (you have to build JCStress first to have jar in your .m2 local repository)

git clone https://github.com/amczarny/JMMPresentation.git
mvn clean install

To start a test you have to execute java -jar target/jmm_jcstress.jar

There are number of command line options. The most useful are
-h help
-l list all tests
-v verbose output (use it to have test result on console)
-t <test name> execute test which match provided regex pattern

After execution, framework will generate html file with reports inside results folder. For command line use it is better to add -v for verbose output
To run StoreLoad test
java -jar target/jmm_jcstress.jar -v -t StoreLoad


Reading the results back...
Generating the report...
 (ETA:        n/a) (R: 0.00E+00) (T:   1/0) (F: 1/1) (I: 1/5)       [OK] jcstress.StoreLoad
  Observed state   Occurrences       Expectation  Interpretation
          [1, 1]        41,346        ACCEPTABLE  Both actors have finished in the same time
          [0, 1]        34,507        ACCEPTABLE  First Actor have finished before second
          [1, 0]    39,358,089        ACCEPTABLE  Second Actors have finished before first
          [0, 0]         5,978   ACCEPTABLE_SPEC  Intel can reorder Stores with Load

Now we can run the same test and set cpu affinity to single core
on windows
start /b /affinity 1 java -jar target/jmm_jcstress.jar -v -t StoreLoad
or linux
taskset -c 1  java -jar target/jmm_jcstress.jar -v -t StoreLoad

The StoreLoad reordering [0,0] should not be visible on single CPU as both threads will have access to the same caches and store buffer.

Reading the results back...
Generating the report...
 (ETA:        n/a) (R: 0.00E+00) (T:   1/0) (F: 1/1) (I: 1/5)       [OK] jcstress.StoreLoad
  Observed state   Occurrences       Expectation  Interpretation
          [1, 1]            14        ACCEPTABLE  Both actors have finished in the same time
          [0, 1]             0        ACCEPTABLE  First Actor have finished before second
          [1, 0]           146        ACCEPTABLE  Second Actors have finished before first
          [0, 0]             0   ACCEPTABLE_SPEC  Intel can reorder Stores with Load


No comments:

Post a Comment