Skip to content

Commit a333f15

Browse files
committed
Added performance metric for frame duration which includes time to write to shared memory.
1 parent 024630b commit a333f15

File tree

3 files changed

+47
-23
lines changed

3 files changed

+47
-23
lines changed

src/main/java/bwapi/BWClient.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Client class to connect to the game with.
99
*/
1010
public class BWClient {
11+
private BWClientConfiguration configuration = new BWClientConfiguration();
1112
private final BWEventListener eventListener;
1213
private BotWrapper botWrapper;
1314
private Client client;
@@ -35,6 +36,13 @@ public PerformanceMetrics getPerformanceMetrics() {
3536
return performanceMetrics;
3637
}
3738

39+
/**
40+
* @return The current configuration
41+
*/
42+
public BWClientConfiguration getConfiguration() {
43+
return configuration;
44+
}
45+
3846
/**
3947
* @return The number of frames between the one exposed to the bot and the most recent received by JBWAPI.
4048
* This tracks the size of the frame buffer except when the game is paused (which results in multiple frames arriving with the same count).
@@ -73,10 +81,12 @@ public void startGame(boolean autoContinue) {
7381
/**
7482
* Start the game.
7583
*
76-
* @param configuration Settings for playing games with this client.
84+
* @param gameConfiguration Settings for playing games with this client.
7785
*/
78-
public void startGame(BWClientConfiguration configuration) {
79-
configuration.validate();
86+
public void startGame(BWClientConfiguration gameConfiguration) {
87+
gameConfiguration.validate();
88+
this.configuration = gameConfiguration;
89+
this.performanceMetrics = new PerformanceMetrics(configuration);
8090
botWrapper = new BotWrapper(configuration, eventListener);
8191

8292
// Use reduced priority to encourage Windows to give priority to StarCraft.exe/BWAPI.
@@ -87,7 +97,7 @@ public void startGame(BWClientConfiguration configuration) {
8797
}
8898

8999
if (client == null) {
90-
client = new Client(configuration);
100+
client = new Client(this);
91101
}
92102
client.reconnect();
93103

@@ -107,7 +117,8 @@ public void startGame(BWClientConfiguration configuration) {
107117
boolean timeFrame = liveGameData.getFrameCount() > 0 || ! configuration.unlimitedFrameZero;
108118

109119
long ticksBefore = Kernel32.INSTANCE.GetTickCount();
110-
performanceMetrics.totalFrameDuration.timeIf(
120+
performanceMetrics.endToEndFrameDuration.startTiming();
121+
performanceMetrics.jbwapiFrameDuration.timeIf(
111122
timeFrame,
112123
() -> {
113124
botWrapper.onFrame();
@@ -116,7 +127,7 @@ public void startGame(BWClientConfiguration configuration) {
116127
long ticksAfter = Kernel32.INSTANCE.GetTickCount();
117128
if (timeFrame) {
118129
long deltaTicks = ticksAfter - ticksBefore;
119-
long deltaMillis = (long) performanceMetrics.totalFrameDuration.runningTotal.last;
130+
long deltaMillis = (long) performanceMetrics.jbwapiFrameDuration.runningTotal.last;
120131
long delta = deltaMillis - deltaTicks;
121132
if (Math.abs(delta) > 1000) {
122133
System.out.println("Got weird tick delta: " + ticksAfter + ", " + ticksBefore + ", " + deltaTicks + ", " + deltaMillis + ", " + delta);

src/main/java/bwapi/Client.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,14 @@ interface MappingKernel extends Kernel32 {
4545
private static final int SUPPORTED_BWAPI_VERSION = 10003;
4646

4747
private ClientData clientData;
48+
private BWClient bwClient;
4849
private boolean connected = false;
4950
private RandomAccessFile pipeObjectHandle = null;
5051
private ByteBuffer gameTableFileHandle = null;
5152
private ByteBuffer mapFileHandle = null;
5253

53-
private BWClientConfiguration configuration = new BWClientConfiguration();
54-
55-
Client(BWClientConfiguration configuration) {
56-
this.configuration = configuration;
54+
Client(BWClient bwClient) {
55+
this.bwClient = bwClient;
5756
}
5857

5958
/**
@@ -83,7 +82,7 @@ void reconnect() {
8382
}
8483

8584
private void disconnect() {
86-
if (configuration.debugConnection) {
85+
if (bwClient.getConfiguration().debugConnection) {
8786
System.err.print("Disconnect called by: ");
8887
System.err.println(Thread.currentThread().getStackTrace()[2]);
8988
}
@@ -134,7 +133,7 @@ boolean connect() {
134133
}
135134
catch (Exception e) {
136135
System.err.println("Unable to map Game table.");
137-
if (configuration.debugConnection) {
136+
if (bwClient.getConfiguration().debugConnection) {
138137
e.printStackTrace();
139138
}
140139
return false;
@@ -168,7 +167,7 @@ boolean connect() {
168167
}
169168
catch (Exception e) {
170169
System.err.println("Unable to open communications pipe: " + communicationPipe);
171-
if (configuration.debugConnection) {
170+
if (bwClient.getConfiguration().debugConnection) {
172171
e.printStackTrace();
173172
}
174173
gameTableFileHandle = null;
@@ -184,7 +183,7 @@ boolean connect() {
184183
}
185184
catch (Exception e) {
186185
System.err.println("Unable to open shared memory mapping: " + sharedMemoryName);
187-
if (configuration.debugConnection) {
186+
if (bwClient.getConfiguration().debugConnection) {
188187
e.printStackTrace();
189188
}
190189
pipeObjectHandle = null;
@@ -197,7 +196,7 @@ boolean connect() {
197196
}
198197
catch (Exception e) {
199198
System.err.println("Unable to map game data.");
200-
if (configuration.debugConnection) {
199+
if (bwClient.getConfiguration().debugConnection) {
201200
e.printStackTrace();
202201
}
203202
return false;
@@ -218,7 +217,7 @@ boolean connect() {
218217
}
219218
catch (Exception e) {
220219
System.err.println("Unable to read pipe object.");
221-
if (configuration.debugConnection) {
220+
if (bwClient.getConfiguration().debugConnection) {
222221
e.printStackTrace();
223222
}
224223
disconnect();
@@ -232,18 +231,21 @@ boolean connect() {
232231
}
233232

234233
void update() {
234+
// Indicate that we are done with the current frame
235235
byte code = 1;
236236
try {
237237
pipeObjectHandle.writeByte(code);
238+
bwClient.getPerformanceMetrics().endToEndFrameDuration.stopTiming();
238239
}
239240
catch (Exception e) {
240241
System.err.println("failed, disconnecting");
241-
if (configuration.debugConnection) {
242+
if (bwClient.getConfiguration().debugConnection) {
242243
e.printStackTrace();
243244
}
244245
disconnect();
245246
return;
246247
}
248+
// Wait for BWAPI to indicate that a new frame is ready
247249
while (code != 2) {
248250
try {
249251
code = pipeObjectHandle.readByte();
@@ -257,7 +259,7 @@ void update() {
257259
}
258260
catch (Exception e) {
259261
System.err.println("failed, disconnecting");
260-
if (configuration.debugConnection) {
262+
if (bwClient.getConfiguration().debugConnection) {
261263
e.printStackTrace();
262264
}
263265
disconnect();

src/main/java/bwapi/PerformanceMetrics.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,20 @@
66
public class PerformanceMetrics {
77

88
/**
9-
* Total duration of the frame from JBWAPI's perspective.
10-
* Likely to be at least a little bit of an undercount,
9+
* Total duration of the frame from JBWAPI's perspective,
10+
* exclusive of time modifying shared memory to indicate frame completion.
11+
* Likely to be at least a little bit of an undercount from the perspective of BWAPI,
1112
* given that the tournament module is timing a superset of JBWAPI's execution time.
1213
*/
13-
PerformanceMetric totalFrameDuration;
14+
PerformanceMetric jbwapiFrameDuration;
15+
16+
/**
17+
* Total duration of the frame from JBWAPI's perspective,
18+
* inclusive of time modifying shared memory to indicate frame completion.
19+
* Likely to be at least a little bit of an undercount from the perspective of BWAPI,
20+
* given that the tournament module is timing a superset of JBWAPI's execution time.
21+
*/
22+
PerformanceMetric endToEndFrameDuration;
1423

1524
/**
1625
* Time spent copying game data from system pipe shared memory to a frame buffer.
@@ -92,7 +101,8 @@ public class PerformanceMetrics {
92101
}
93102

94103
public void reset() {
95-
totalFrameDuration = new PerformanceMetric("JBWAPI frame duration", 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 85);
104+
jbwapiFrameDuration = new PerformanceMetric("JBWAPI frame duration", 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 85);
105+
endToEndFrameDuration = new PerformanceMetric("End-to-end frame duration", 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 85);
96106
copyingToBuffer = new PerformanceMetric("Time copying to buffer", 5, 10, 15, 20, 25, 30);
97107
intentionallyBlocking = new PerformanceMetric("Blocking with full buffer", 0);
98108
frameBufferSize = new PerformanceMetric("Frames buffered", 0, 1);
@@ -111,7 +121,8 @@ public void reset() {
111121
@Override
112122
public String toString() {
113123
return "Performance metrics:"
114-
+ "\n" + totalFrameDuration.toString()
124+
+ "\n" + jbwapiFrameDuration.toString()
125+
+ "\n" + endToEndFrameDuration.toString()
115126
+ "\n" + copyingToBuffer.toString()
116127
+ "\n" + intentionallyBlocking.toString()
117128
+ "\n" + frameBufferSize.toString()

0 commit comments

Comments
 (0)