Skip to content

Commit edddd2b

Browse files
committed
Fixed condition for waiting for bot to finish (instead of returning control immediately always). Improved some metrics
1 parent be52a24 commit edddd2b

File tree

6 files changed

+58
-57
lines changed

6 files changed

+58
-57
lines changed

src/main/java/bwapi/BWClient.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
public class BWClient {
99
private final BWEventListener eventListener;
1010
private BotWrapper botWrapper;
11+
private Client client;
1112
private PerformanceMetrics performanceMetrics;
1213

1314
public BWClient(final BWEventListener eventListener) {
@@ -31,6 +32,13 @@ public PerformanceMetrics getPerformanceMetrics() {
3132
return performanceMetrics;
3233
}
3334

35+
/**
36+
* Number of frames
37+
*/
38+
public int framesBehind() {
39+
return botWrapper == null ? 0 : client.clientData().gameData().getFrameCount() - getGame().getFrameCount();
40+
}
41+
3442
public void startGame() {
3543
BWClientConfiguration configuration = new BWClientConfiguration();
3644
startGame(configuration);
@@ -57,7 +65,7 @@ public void startGame(BWClientConfiguration configuration) {
5765
configuration.validate();
5866
botWrapper = new BotWrapper(configuration, eventListener);
5967

60-
Client client = new Client(configuration);
68+
client = new Client(configuration);
6169
client.reconnect();
6270

6371
do {
@@ -73,16 +81,16 @@ public void startGame(BWClientConfiguration configuration) {
7381
}
7482
}
7583
while (liveGameData.isInGame()) {
76-
performanceMetrics.totalFrameDuration.time(() -> {
77-
botWrapper.onFrame();
78-
performanceMetrics.flushSideEffects.time(() -> {
79-
getGame().sideEffects.flushTo(liveGameData);
80-
});
81-
client.update();
82-
if (!client.isConnected()) {
83-
client.reconnect();
84-
}
85-
});
84+
if (liveGameData.getFrameCount() > 0 || ! configuration.unlimitedFrameZero) {
85+
performanceMetrics.totalFrameDuration.startTiming();
86+
}
87+
botWrapper.onFrame();
88+
performanceMetrics.flushSideEffects.time(() -> getGame().sideEffects.flushTo(liveGameData));
89+
client.update();
90+
if (!client.isConnected()) {
91+
client.reconnect();
92+
}
93+
performanceMetrics.totalFrameDuration.stopTiming();
8694
}
8795
botWrapper.endGame();
8896
} while (configuration.autoContinue);

src/main/java/bwapi/BWClientConfiguration.java

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ public class BWClientConfiguration {
1515
*/
1616
public boolean autoContinue = false;
1717

18+
/**
19+
* Most bot tournaments allow bots to take an indefinite amount of time on frame #0 (the first frame of the game) to analyze the map and load data,
20+
* as the bot has no prior access to BWAPI or game information.
21+
*
22+
* This flag indicates that taking arbitrarily long on frame zero is acceptable.
23+
* Performance metrics omit the frame as an outlier.
24+
* Asynchronous operation will block until the bot's event handlers are complete.
25+
*/
26+
public boolean unlimitedFrameZero = true;
27+
1828
/**
1929
* Runs the bot in asynchronous mode. Asynchronous mode helps attempt to ensure that the bot adheres to real-time performance constraints.
2030
*
@@ -32,29 +42,14 @@ public class BWClientConfiguration {
3242
* If JBWAPI detects that this much time (in nanoseconds) has passed since a bot's event handlers began, returns control back to BWAPI.
3343
* Real-time human play typically uses the "fastest" game speed, which has 42.86ms (42,860ns) between frames.
3444
*/
35-
public int asyncFrameDurationMs = 40000;
45+
public int asyncFrameDurationMs = 40;
3646

3747
/**
3848
* The maximum number of frames to buffer while waiting on a bot.
3949
* Each frame buffered adds about 33 megabytes to JBWAPI's memory footprint.
4050
*/
4151
public int asyncFrameBufferSize = 10;
4252

43-
/**
44-
* Most bot tournaments allow bots to take an indefinite amount of time on frame #0 (the first frame of the game) to analyze the map and load data,
45-
* as the bot has no prior access to BWAPI or game information.
46-
*
47-
* This flag causes JBWAPI to wait for the bot's event handlers to return on the first frame of the game, even if operating in asynchronous mode,
48-
* respecting the time bots are typically allowed on frame 0.
49-
*/
50-
public boolean asyncWaitOnFrameZero = true;
51-
52-
/**
53-
* Enables collection of diagnostics.
54-
* When timersEnabled, JBWAPI collects and publishes performance metrics.
55-
*/
56-
public boolean collectPerformanceMetrics = false;
57-
5853
/**
5954
* Checks that the configuration is in a valid state. Throws an IllegalArgumentException if it isn't.
6055
*/

src/main/java/bwapi/BotWrapper.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,29 @@ void onFrame() {
7878
botThread.setName("JBWAPI Bot");
7979
botThread.start();
8080
}
81-
performanceMetrics.copyingToBuffer.time(frameBuffer::enqueueFrame);
81+
/*
82+
Add a frame to buffer
83+
If buffer is full, it will wait until it has capacity
84+
Wait for empty buffer OR termination condition
85+
*/
86+
boolean isFrameZero = liveClientData.gameData().getFrameCount() == 0;
87+
frameBuffer.enqueueFrame();
88+
performanceMetrics.bwapiResponse.startTiming();
8289
frameBuffer.lockSize.lock();
8390
try {
84-
while (frameBuffer.empty()) {
85-
performanceMetrics.bwapiResponse.startTiming();
86-
if (configuration.asyncWaitOnFrameZero && liveClientData.gameData().getFrameCount() == 0) {
91+
while (!frameBuffer.empty()) {
92+
if (configuration.unlimitedFrameZero && isFrameZero) {
8793
frameBuffer.conditionSize.await();
8894
} else {
8995
long remainingNanos = endNanos - System.nanoTime();
9096
if (remainingNanos <= 0) break;
9197
frameBuffer.conditionSize.awaitNanos(remainingNanos);
9298
}
9399
}
94-
performanceMetrics.bwapiResponse.stopTiming();
95100
} catch(InterruptedException ignored) {
96101
} finally {
97102
frameBuffer.lockSize.unlock();
103+
performanceMetrics.bwapiResponse.stopTiming();
98104
}
99105
} else {
100106
handleEvents();
@@ -135,7 +141,7 @@ private Thread createBotThread() {
135141

136142
private void handleEvents() {
137143
ClientData.GameData gameData = game.clientData().gameData();
138-
if (gameData.getFrameCount() > 0 || ! configuration.asyncWaitOnFrameZero) {
144+
if (gameData.getFrameCount() > 0 || ! configuration.unlimitedFrameZero) {
139145
performanceMetrics.botResponse.startTiming();
140146
}
141147
for (int i = 0; i < gameData.getEventCount(); i++) {

src/main/java/bwapi/FrameBuffer.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,13 @@ void enqueueFrame() {
119119
}
120120
performanceMetrics.intentionallyBlocking.stopTiming();
121121
} finally { lockSize.unlock(); };
122-
ByteBuffer dataTarget = dataBuffer.get(indexGame());
123-
dataSource.rewind();
124-
dataTarget.rewind();
125-
dataTarget.put(dataSource);
122+
123+
performanceMetrics.copyingToBuffer.time(() -> {
124+
ByteBuffer dataTarget = dataBuffer.get(indexGame());
125+
dataSource.rewind();
126+
dataTarget.rewind();
127+
dataTarget.put(dataSource);
128+
});
126129

127130
lockSize.lock();
128131
try {

src/main/java/bwapi/PerformanceMetric.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
public class PerformanceMetric {
66
private final String name;
77
private final long maxAllowed;
8-
public final boolean timerEnabled;
98

109
public double minValue = Long.MAX_VALUE;
1110
public double maxValue = Long.MIN_VALUE;
@@ -17,10 +16,9 @@ public class PerformanceMetric {
1716

1817
private long timeStarted = 0;
1918

20-
PerformanceMetric(String name, long maxAllowed, boolean timerEnabled) {
19+
PerformanceMetric(String name, long maxAllowed) {
2120
this.name = name;
2221
this.maxAllowed = maxAllowed;
23-
this.timerEnabled = timerEnabled;
2422
}
2523

2624
void time(Runnable runnable) {
@@ -30,15 +28,13 @@ void time(Runnable runnable) {
3028
}
3129

3230
void startTiming() {
33-
if (!timerEnabled) return;
3431
if (timeStarted > 0) {
3532
++interrupted;
3633
}
3734
timeStarted = System.nanoTime();
3835
}
3936

4037
void stopTiming() {
41-
if (!timerEnabled) return;
4238
if (timeStarted <= 0) return;
4339
// Use nanosecond resolution timer, but record in units of milliseconds.
4440
long timeEnded = System.nanoTime();

src/main/java/bwapi/PerformanceMetrics.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,31 +45,24 @@ public class PerformanceMetrics {
4545
*/
4646
public PerformanceMetric bwapiResponse;
4747

48-
/**
49-
* Whether performance timers have been enabled in the JBWAPI configuration.
50-
* Timers are off by default to spare performance.
51-
*/
52-
public final boolean timersEnabled;
53-
5448
/**
5549
* Time bot spends idle.
5650
* Applicable only in asynchronous mode.
5751
*/
5852
public PerformanceMetric botIdle;
5953

6054
public PerformanceMetrics(BWClientConfiguration configuration) {
61-
timersEnabled = configuration.collectPerformanceMetrics;
6255
final int frameDurationBufferMs = 5;
6356
final int sideEffectsBufferMs = 1;
6457
final int realTimeFrameMs = 42;
65-
totalFrameDuration = new PerformanceMetric("Total frame duration", configuration.asyncFrameDurationMs + frameDurationBufferMs, timersEnabled);
66-
copyingToBuffer = new PerformanceMetric("Time copying to buffer", 5, timersEnabled);
67-
intentionallyBlocking = new PerformanceMetric("Intentionally blocking", 0, timersEnabled);
68-
frameBufferSize = new PerformanceMetric("Frames buffered", 0, timersEnabled);
69-
flushSideEffects = new PerformanceMetric("Flush side effects", sideEffectsBufferMs , timersEnabled);
70-
botResponse = new PerformanceMetric("Bot Responses", configuration.asyncFrameDurationMs, timersEnabled);
71-
bwapiResponse = new PerformanceMetric("BWAPI Responses", realTimeFrameMs, timersEnabled);
72-
botIdle = new PerformanceMetric("Bot idle", Long.MAX_VALUE, timersEnabled);
58+
totalFrameDuration = new PerformanceMetric("Total frame duration", configuration.asyncFrameDurationMs + frameDurationBufferMs);
59+
copyingToBuffer = new PerformanceMetric("Time copying to buffer", 5);
60+
intentionallyBlocking = new PerformanceMetric("Intentionally blocking", 0);
61+
frameBufferSize = new PerformanceMetric("Frames buffered", 0);
62+
flushSideEffects = new PerformanceMetric("Flush side effects", sideEffectsBufferMs );
63+
botResponse = new PerformanceMetric("Bot Responses", configuration.asyncFrameDurationMs);
64+
bwapiResponse = new PerformanceMetric("BWAPI Responses", realTimeFrameMs);
65+
botIdle = new PerformanceMetric("Bot idle", Long.MAX_VALUE);
7366
}
7467

7568
@Override

0 commit comments

Comments
 (0)