1
1
package bwapi ;
2
2
3
- import com .sun .jna .Platform ;
4
- import sun .nio .ch .DirectBuffer ;
5
- import java .nio .ByteBuffer ;
3
+ import sun .misc .Unsafe ;
4
+
6
5
import java .util .ArrayList ;
7
6
import java .util .concurrent .locks .Condition ;
8
7
import java .util .concurrent .locks .Lock ;
13
12
*/
14
13
class FrameBuffer {
15
14
private static final int BUFFER_SIZE = ClientData .GameData .SIZE ;
15
+ private static final Unsafe unsafe = UnsafeTools .getUnsafe ();
16
16
17
17
private WrappedBuffer liveData ;
18
18
private PerformanceMetrics performanceMetrics ;
@@ -158,24 +158,11 @@ void dequeue() {
158
158
* @param source Address to copy from
159
159
* @param destination Address to copy to
160
160
* @param size Number of bytes to copy
161
- * @return True if the copy succeeded
162
161
*/
163
- private boolean tryMemcpyBuffer (WrappedBuffer source , WrappedBuffer destination , long offset , int size ) {
162
+ private void copyBuffer (WrappedBuffer source , WrappedBuffer destination , long offset , int size ) {
164
163
long addressSource = source .getAddress () + offset ;
165
164
long addressDestination = destination .getAddress () + offset ;
166
- try {
167
- if (Platform .isWindows ()) {
168
- if (Platform .is64Bit ()) {
169
- MSVCRT .INSTANCE .memcpy (addressDestination , addressSource , size );
170
- return true ;
171
- } else {
172
- MSVCRT .INSTANCE .memcpy ((int ) addressDestination , (int ) addressSource , size );
173
- return true ;
174
- }
175
- }
176
- }
177
- catch (Exception ignored ) {}
178
- return false ;
165
+ unsafe .copyMemory (addressSource , addressDestination , size );
179
166
}
180
167
181
168
void copyBuffer (WrappedBuffer source , WrappedBuffer destination , boolean copyEverything ) {
@@ -185,16 +172,10 @@ void copyBuffer(WrappedBuffer source, WrappedBuffer destination, boolean copyEve
185
172
but are prone to large amounts of variance.
186
173
187
174
The normal Java way to execute this copy is via ByteBuffer.put(), which has reasonably good performance characteristics.
188
- Experiments in 64-bit JRE have shown that using a native memcpy achieves a 35% speedup.
189
- Experiments in 32-bit JRE show no difference in performance.
190
-
191
- So, speculatively, we attempt to do a native memcpy.
192
175
*/
193
176
194
177
if (copyEverything ) {
195
- if (tryMemcpyBuffer (source , destination , 0 , FrameBuffer .BUFFER_SIZE )) {
196
- return ;
197
- }
178
+ copyBuffer (source , destination , 0 , FrameBuffer .BUFFER_SIZE );
198
179
} else {
199
180
// After the buffer has been filled the first time,
200
181
// we can omit copying blocks of data which are unused or which don't change after game start.
@@ -207,18 +188,10 @@ void copyBuffer(WrappedBuffer source, WrappedBuffer destination, boolean copyEve
207
188
final int STRINGSSHAPES_START = 10962632 ; // getStringCount, ... getShapes
208
189
final int STRINGSHAPES_END = 32242636 ;
209
190
final int UNITFINDER_START = 32962644 ;
210
- if (
211
- tryMemcpyBuffer (source , destination , 0 , STATICTILES_START )
212
- && tryMemcpyBuffer (source , destination , STATICTILES_END , REGION_START - STATICTILES_END )
213
- && tryMemcpyBuffer (source , destination , REGION_END , STRINGSSHAPES_START - REGION_END )
214
- && tryMemcpyBuffer (source , destination , STRINGSHAPES_END , UNITFINDER_START - STRINGSHAPES_END )) {
215
- return ;
216
- }
191
+ copyBuffer (source , destination , 0 , STATICTILES_START );
192
+ copyBuffer (source , destination , STATICTILES_END , REGION_START - STATICTILES_END );
193
+ copyBuffer (source , destination , REGION_END , STRINGSSHAPES_START - REGION_END );
194
+ copyBuffer (source , destination , STRINGSHAPES_END , UNITFINDER_START - STRINGSHAPES_END );
217
195
}
218
-
219
- // There's no specific case where we expect to fail above,
220
- // but this is a safe fallback regardless,
221
- // and serves to document the known-good (and cross-platform, for BWAPI 5) way to executing the copy.
222
- destination .copyFrom (source );
223
196
}
224
197
}
0 commit comments