Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CODETOOLS-7902943: jcstress: Update console UX again #53

Merged
merged 6 commits into from
May 25, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -92,6 +92,8 @@ public void run() throws Exception {
SerializedBufferCollector sink = new SerializedBufferCollector(mux);

TestExecutor executor = new TestExecutor(opts.verbosity(), sink, scheduler);
printer.setExecutor(executor);

executor.runAll(configs);

sink.close();
20 changes: 20 additions & 0 deletions jcstress-core/src/main/java/org/openjdk/jcstress/TestExecutor.java
Original file line number Diff line number Diff line change
@@ -63,6 +63,8 @@ public class TestExecutor {
private final Map<Integer, VM> vmByToken;
private final Object notifyLock;

private final AtomicInteger jvmsRunning;

public TestExecutor(Verbosity verbosity, TestResultCollector sink, Scheduler scheduler) throws IOException {
this.verbosity = verbosity;
this.sink = sink;
@@ -82,6 +84,8 @@ public void onResult(int token, TestResult result) {
notifyChanged();
}
});

this.jvmsRunning = new AtomicInteger();
}

private void awaitNotification() {
@@ -169,6 +173,18 @@ private boolean processReadyVMs() {
return reclaimed;
}

public int getActorCpus() {
return scheduler.getActorCpus();
}

public int getSystemCpus() {
return scheduler.getSystemCpus();
}

public int getJVMsRunning() {
return jvmsRunning.get();
}

private class VM {
private final String host;
private final int port;
@@ -335,6 +351,8 @@ void start() {
ProcessBuilder pb = new ProcessBuilder(command);
process = pb.start();

jvmsRunning.incrementAndGet();

// start the stream drainers and read the streams into memory;
// makes little sense to write them to files, since we would be
// reading them back soon anyway
@@ -376,6 +394,8 @@ public synchronized boolean checkCompleted(TestResultCollector sink) {
try {
int ecode = process.waitFor();

jvmsRunning.decrementAndGet();

outCollector.join();
errCollector.join();

Original file line number Diff line number Diff line change
@@ -32,20 +32,32 @@ public enum Expect {
/**
* Acceptable result. Acceptable results are not required to be present.
*/
ACCEPTABLE,
ACCEPTABLE("Acceptable"),

/**
* Same as {@link #ACCEPTABLE}, but this result will be highlighted in reports.
*/
ACCEPTABLE_INTERESTING,
ACCEPTABLE_INTERESTING("Interesting"),

/**
* Forbidden result. Should never be present.
*/
FORBIDDEN,
FORBIDDEN("Forbidden"),

/**
* Internal expectation: no grading. Do not use.
*/
UNKNOWN,
UNKNOWN("Unknown"),
;

private final String desc;

Expect(String desc) {
this.desc = desc;
}

@Override
public String toString() {
return desc;
}
}
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
package org.openjdk.jcstress.infra.grading;

import org.openjdk.jcstress.Options;
import org.openjdk.jcstress.TestExecutor;
import org.openjdk.jcstress.Verbosity;
import org.openjdk.jcstress.infra.collectors.TestResult;
import org.openjdk.jcstress.infra.collectors.TestResultCollector;
@@ -61,6 +62,7 @@ public class ConsoleReportPrinter implements TestResultCollector {
private long failed;
private long softErrors;
private long hardErrors;
private TestExecutor executor;

public ConsoleReportPrinter(Options opts, PrintWriter pw, long expectedForks) {
this.output = pw;
@@ -143,9 +145,13 @@ private void printResult(TestResult r) {

private void printStatusLine() {
long currentTime = System.nanoTime();
String line = String.format("(ETA: %10s) (Sample Rate: %s) (Results: %d planned; %d passed, %d failed, %d soft errs, %d hard errs) ",
final int actorCpus = executor.getActorCpus();
final int systemCpus = executor.getSystemCpus();
String line = String.format("(ETA: %10s) (Sample Rate: %s) (JVMs: %d running) (CPUs: %d actor, %d system, %d total) (Results: %d planned; %d passed, %d failed, %d soft errs, %d hard errs)",
computeETA(),
computeSpeed(),
executor.getJVMsRunning(),
actorCpus, systemCpus, actorCpus + systemCpus,
expectedResults, passed, failed, softErrors, hardErrors
);
progressLen = line.length();
@@ -182,19 +188,19 @@ private String computeSpeed() {
final long G = 1000*M;
final long T = 1000*G;

if (v > 10*T) {
if (v > T) {
return String.format("%3.2f T/sec", v / T);
}

if (v > 10*G) {
if (v > G) {
return String.format("%3.2f G/sec", v / G);
}

if (v > 10*M) {
if (v > M) {
return String.format("%3.2f M/sec", v / M);
}

if (v > 10*K) {
if (v > K) {
return String.format("%3.2f K/sec", v / K);
}

@@ -231,4 +237,7 @@ private String computeETA() {
}
}

public void setExecutor(TestExecutor executor) {
this.executor = executor;
}
}
Original file line number Diff line number Diff line change
@@ -129,14 +129,21 @@ public static void printResult(PrintWriter pw, TestResult r, boolean inProgress)
pw.println();

if (!r.isEmpty()) {
int idLen = "Observed state".length();
int occLen = "Occurrences".length();
int expectLen = "Expectation".length();
final String headResult = "RESULT";
final String headSamples = "SAMPLES";
final String headFreq = "FREQ";
final String headExpect = "EXPECT";
final String headDesc = "DESCRIPTION";

int idLen = headResult.length();
int samplesLen = headSamples.length();
int freqLen = Math.max(6, headFreq.length());
int expectLen = headExpect.length();
int descLen = 60;

for (String s : r.getStateKeys()) {
idLen = Math.max(idLen, s.length());
occLen = Math.max(occLen, String.format("%,d", r.getCount(s)).length());
samplesLen = Math.max(samplesLen, String.format("%,d", r.getCount(s)).length());
expectLen = Math.max(expectLen, Expect.UNKNOWN.toString().length());
}

@@ -148,15 +155,28 @@ public static void printResult(PrintWriter pw, TestResult r, boolean inProgress)
expectLen = Math.max(expectLen, test.unmatched().expect().toString().length());

idLen += 2;
occLen += 2;
samplesLen += 2;
freqLen += 2;
expectLen += 2;

pw.printf("%" + idLen + "s %" + occLen + "s %" + expectLen + "s %-" + descLen + "s%n", "Observed state", "Occurrences", "Expectation", "Interpretation");
pw.printf("%" + idLen + "s%" + samplesLen + "s%" + freqLen + "s%" + expectLen + "s %-" + descLen + "s%n",
headResult, headSamples, headFreq, headExpect, headDesc);

for (GradingResult gradeRes : r.grading().gradingResults) {
pw.printf("%" + idLen + "s %," + occLen + "d %" + expectLen + "s %-" + descLen + "s%n",
TestGrading grade = r.grading();
long totalSamples = 0;
for (GradingResult gradeRes : grade.gradingResults) {
totalSamples += gradeRes.count;
}

if (totalSamples == 0) {
totalSamples = 1;
}

for (GradingResult gradeRes : grade.gradingResults) {
pw.printf("%" + idLen + "s%," + samplesLen + "d%" + freqLen + "s%" + expectLen + "s %-" + descLen + "s%n",
StringUtils.cutoff(gradeRes.id, idLen),
gradeRes.count,
StringUtils.percent(gradeRes.count, totalSamples, 1),
gradeRes.expect,
StringUtils.cutoff(gradeRes.description, descLen));
}
Original file line number Diff line number Diff line change
@@ -100,20 +100,20 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
for (TestInfo test : tests) {
TestLineWriter wl = new TestLineWriter();

wl.put(test.getTest().getQualifiedName());
wl.put(test.getTest().getQualifiedName().toString());
wl.put(test.getGeneratedName());
wl.put(test.getDescription());
List<ExecutableElement> actors = test.getActors();
wl.put(actors.size());
for (ExecutableElement actor : actors) {
wl.put(actor.getSimpleName());
wl.put(actor.getSimpleName().toString());
}
wl.put(test.isRequiresFork());

wl.put(test.cases().size());

for (Outcome c : test.cases()) {
wl.put(c.expect());
wl.put(c.expect().ordinal());
wl.put(c.desc());
wl.put(c.id().length);
for (String id : c.id()) {
Original file line number Diff line number Diff line change
@@ -44,11 +44,12 @@ public class TestList {

private static Map<String, TestInfo> getTests() {
if (tests == null) {
Expect[] expectValues = Expect.values();
Map<String, TestInfo> m = new HashMap<>();
InputStream stream = null;
try {
stream = TestList.class.getResourceAsStream(LIST);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

try (InputStream stream = TestList.class.getResourceAsStream(LIST);
InputStreamReader isr = new InputStreamReader(stream);
BufferedReader reader = new BufferedReader(isr)) {

String line;
while ((line = reader.readLine()) != null) {
@@ -72,8 +73,8 @@ private static Map<String, TestInfo> getTests() {
m.put(name, testInfo);

for (int c = 0; c < caseCount; c++) {
Expect expect = Expect.valueOf(read.nextString());
String desc = read.nextString();
Expect expect = expectValues[read.nextInt()];
String desc = read.nextString();
int stateCount = read.nextInt();
for (int s = 0; s < stateCount; s++) {
String regex = read.nextString();
@@ -90,15 +91,8 @@ private static Map<String, TestInfo> getTests() {
}
} catch (IOException e) {
throw new IllegalStateException("Fatal error", e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// swallow
}
}
}
// swallow
tests = m;
}
return tests;
28 changes: 19 additions & 9 deletions jcstress-core/src/main/java/org/openjdk/jcstress/os/Scheduler.java
Original file line number Diff line number Diff line change
@@ -36,7 +36,8 @@ public class Scheduler {
private final int maxUse;
private final Topology topology;
private final BitSet availableCores;
private int currentUse;
private int currentActorUse;
private int currentSystemUse;
private final PackageRecord[] freeMapPackage;

public Scheduler(Topology t, int max) {
@@ -54,7 +55,7 @@ public Scheduler(Topology t, int max) {
}

public synchronized CPUMap tryAcquire(SchedulingClass scl) {
if (currentUse + scl.numActors() > maxUse) {
if (currentActorUse + scl.numActors() > maxUse) {
// Over the limit, break out.
return null;
}
@@ -153,7 +154,7 @@ private CPUMap scheduleLocal(SchedulingClass scl) {
if (availableCPUs.get(thread)) {
availableCPUs.set(thread, false);
actorMap[aIdx] = thread;
currentUse++;
currentActorUse++;
break;
}
}
@@ -167,7 +168,7 @@ private CPUMap scheduleLocal(SchedulingClass scl) {
if (availableCPUs.get(thread)) {
availableCPUs.set(thread, false);
system[systemCnt++] = thread;
currentUse++;
currentSystemUse++;
}
}
}
@@ -230,7 +231,7 @@ private CPUMap scheduleGlobal(SchedulingClass scl) {
}
availableCPUs.set(thread, false);
system[systemCnt++] = thread;
currentUse++;
currentSystemUse++;
}
}

@@ -279,8 +280,9 @@ private void checkInvariants(String when) {
}
}

if (use != currentUse) {
throw new IllegalStateException(when + ": CPU use counts are inconsistent, counter = " + currentUse + ", actually taken = " + use);
final int expected = currentActorUse + currentSystemUse;
if (use != expected) {
throw new IllegalStateException(when + ": CPU use counts are inconsistent, counter = " + expected + ", actually taken = " + use);
}

for (int p = 0; p < topology.packagesPerSystem(); p++) {
@@ -305,13 +307,13 @@ public synchronized void release(CPUMap cpuMap) {
if (c != -1) {
availableCPUs.set(c, true);
availableCores.set(topology.threadToCore(c), true);
currentUse--;
currentActorUse--;
}
}
for (int c : cpuMap.systemMap()) {
availableCPUs.set(c, true);
availableCores.set(topology.threadToCore(c), true);
currentUse--;
currentSystemUse--;
}

recomputeFreeMaps();
@@ -334,6 +336,14 @@ private void recomputeFreeMaps() {
Arrays.sort(freeMapPackage);
}

public int getActorCpus() {
return currentActorUse;
}

public int getSystemCpus() {
return currentSystemUse;
}

private static class PackageRecord implements Comparable<PackageRecord> {
int id;
int avail;
Original file line number Diff line number Diff line change
@@ -167,4 +167,14 @@ public static List<Integer> decodeCpuList(String line) {
}
return r;
}

public static String percent(long v, long total, int prec) {
double p = v * 100.0 / total;
double limit = Math.pow(0.1, prec);
if (p < limit) {
return String.format("<%." + prec + "f%%", limit);
} else {
return String.format("%." + prec + "f%%", p);
}
}
}
Loading