13
13
import java .util .concurrent .locks .Lock ;
14
14
import java .util .concurrent .locks .ReentrantLock ;
15
15
16
+ import com .google .common .base .Stopwatch ;
17
+ import com .rs2 .game .npcs .Npc ;
18
+ import com .rs2 .game .npcs .NpcList ;
16
19
import com .rs2 .gui .ControlPanel ;
17
20
18
21
import org .apollo .cache .IndexedFileSystem ;
@@ -239,33 +242,72 @@ public static void main(java.lang.String[] args)
239
242
* scheduleAtFixedRate() does not invoke concurrent Runnables.
240
243
*/
241
244
scheduler .scheduleAtFixedRate (new Runnable () {
245
+ int gameTicksIncrementor ;
246
+ final int printInfoTick = Constants .CYCLE_LOGGING_TICK ;
242
247
public void run () {
243
- //TODO debug Stopwatch stopwatch = Stopwatch.createStarted();
248
+ Stopwatch stopwatch = Stopwatch .createStarted ();
244
249
/**
245
250
* Main Server Tick
246
251
*/
247
252
try {
248
253
if (GameEngine .shutdownServer ) {
249
254
scheduler .shutdown ();
250
255
}
256
+ long startItemHandler = System .currentTimeMillis ();
251
257
itemHandler .process ();
258
+ long durationItemHandler = System .currentTimeMillis () - startItemHandler ;
259
+ checkAndLogDuration ("ItemHandler" , durationItemHandler );
260
+ long startPlayerHandler = System .currentTimeMillis ();
252
261
playerHandler .process ();
262
+ long durationPlayerHandler = System .currentTimeMillis () - startPlayerHandler ;
263
+ checkAndLogDuration ("PlayerHandler" , durationPlayerHandler );
264
+ long startNpcHandler = System .currentTimeMillis ();
253
265
npcHandler .process ();
266
+ long durationNpcHandler = System .currentTimeMillis () - startNpcHandler ;
267
+ checkAndLogDuration ("NpcHandler" , durationNpcHandler );
268
+ long startShopHandler = System .currentTimeMillis ();
254
269
shopHandler .process ();
270
+ long durationShopHandler = System .currentTimeMillis () - startShopHandler ;
271
+ checkAndLogDuration ("ShopHandler" , durationShopHandler );
272
+ long startObjectManager = System .currentTimeMillis ();
255
273
objectManager .process ();
274
+ long durationObjectManager = System .currentTimeMillis () - startObjectManager ;
275
+ checkAndLogDuration ("ObjectManager" , durationObjectManager );
276
+ long startCastleWars = System .currentTimeMillis ();
256
277
CastleWars .process ();
278
+ long durationCastleWars = System .currentTimeMillis () - startCastleWars ;
279
+ checkAndLogDuration ("CastleWars" , durationCastleWars );
280
+ long startFightPits = System .currentTimeMillis ();
257
281
FightPits .process ();
282
+ long durationFightPits = System .currentTimeMillis () - startFightPits ;
283
+ checkAndLogDuration ("FightPits" , durationFightPits );
284
+ long startPestControl = System .currentTimeMillis ();
258
285
pestControl .process ();
286
+ long durationPestControl = System .currentTimeMillis () - startPestControl ;
287
+ checkAndLogDuration ("PestControl" , durationPestControl );
288
+ long startObjectHandler = System .currentTimeMillis ();
259
289
objectHandler .process ();
290
+ long durationObjectHandler = System .currentTimeMillis () - startObjectHandler ;
291
+ checkAndLogDuration ("CastleWars" , durationObjectHandler );
292
+ long startMageTrainingArena = System .currentTimeMillis ();
260
293
MageTrainingArena .process ();
294
+ long durationMageTrainingArena = System .currentTimeMillis () - startMageTrainingArena ;
295
+ checkAndLogDuration ("MageTrainingArena" , durationMageTrainingArena );
296
+ long startCycleEventHandler = System .currentTimeMillis ();
261
297
CycleEventHandler .getSingleton ().process ();
298
+ long durationCycleEventHandler = System .currentTimeMillis () - startCycleEventHandler ;
299
+ checkAndLogDuration ("CycleEventHandler" , durationCycleEventHandler );
300
+ long startIntegrationEvents = System .currentTimeMillis ();
262
301
if (Constants .WEBSITE_INTEGRATION ) {
263
302
PlayersOnlineWebsite .addUpdatePlayersOnlineTask ();
264
303
RegisteredAccsWebsite .addUpdateRegisteredUsersTask ();
265
304
}
266
305
if (DiscordActivity .playerCount ) {
267
306
DiscordActivity .updateActivity ();
268
307
}
308
+ long durationIntegrationEvents = System .currentTimeMillis () - startIntegrationEvents ;
309
+ checkAndLogDuration ("IntegrationEvents" , durationIntegrationEvents );
310
+ long startSaveEvents = System .currentTimeMillis ();
269
311
if (System .currentTimeMillis () - lastMassSave > 300000 ) {
270
312
for (Player p : PlayerHandler .players ) {
271
313
if (p == null ) {
@@ -276,9 +318,42 @@ public void run() {
276
318
lastMassSave = System .currentTimeMillis ();
277
319
}
278
320
}
321
+ long durationSaveEvents = System .currentTimeMillis () - startSaveEvents ;
322
+ checkAndLogDuration ("SaveEvents" , durationSaveEvents );
323
+ long totalCycleDuration = stopwatch .elapsed (TimeUnit .MILLISECONDS );
324
+ //Technically, we could add commands to test both client lag (creating many tile objects) and server lag (creating a BCrypt hash on game thread)
325
+ if (totalCycleDuration > 500 ) {
326
+ System .err .println ("ERROR: Cycle duration exceeded 500 ms!" );
327
+ } else if (totalCycleDuration > 250 ) {
328
+ System .err .println ("WARNING: Cycle duration exceeded 250 ms!" );
329
+ } else if (totalCycleDuration > 100 ) {
330
+ System .out .println ("NOTICE: Cycle duration exceeded 100 ms." );
331
+ }
332
+ gameTicksIncrementor ++;
333
+ if (Constants .CYCLE_LOGGING && gameTicksIncrementor > 1 && gameTicksIncrementor % printInfoTick == 0 ) {
334
+ long totalMem = Runtime .getRuntime ().totalMemory ();
335
+ long freeMem = Runtime .getRuntime ().freeMemory ();
336
+ long maxMem = Runtime .getRuntime ().maxMemory ();
337
+ int playerCount = 0 ;
338
+ for (Player p : PlayerHandler .players ) {
339
+ if (p != null ) {
340
+ playerCount ++;
341
+ }
342
+ }
343
+ int npcCount = 0 ;
344
+ for (Npc npc : NpcHandler .npcs ) {
345
+ if (npc != null ) {
346
+ npcCount ++;
347
+ }
348
+ }
349
+ System .out .println ("Cycle #" + gameTicksIncrementor + " took " + totalCycleDuration + " ms. Players: " + playerCount + ", NPCs: " + npcCount +
350
+ ", [Durations: i: " + durationItemHandler + " ms, p: " + durationPlayerHandler + " ms, n: " + durationNpcHandler + " ms, s: " + durationShopHandler +
351
+ " ms, oh: " + durationObjectHandler + " ms, om: " + durationObjectManager + " ms], Memory: " + (totalMem - freeMem ) / 1024 / 1024 + "MB/" +
352
+ totalMem / 1024 / 1024 + "MB. Max: " + maxMem / 1024 / 1024 + "MB, Threads: " + Thread .activeCount () + "." );
353
+ }
279
354
} catch (Exception ex ) {
280
355
ex .printStackTrace ();
281
- System .out .println ("A fatal exception has been thrown! " );
356
+ System .err .println ("A fatal exception has been thrown in the GameEngine cycle! Saving all players. " );
282
357
for (Player p : PlayerHandler .players ) {
283
358
if (p == null ) {
284
359
continue ;
@@ -294,7 +369,6 @@ public void run() {
294
369
}
295
370
scheduler .shutdown (); // Kills the tickloop thread if Exception is thrown.
296
371
}
297
- //TODO debug System.out.println("Cycle took " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms.");
298
372
}
299
373
}, 0 , Constants .CYCLE_TIME , TimeUnit .MILLISECONDS );
300
374
@@ -315,6 +389,16 @@ public void run() {
315
389
316
390
System .exit (0 );
317
391
}
392
+
393
+ private static void checkAndLogDuration (String processName , long duration ) {
394
+ if (duration > 500 ) {
395
+ System .err .println ("ERROR: " + processName + " duration exceeded 500 ms! Duration: " + duration + " ms." );
396
+ } else if (duration > 250 ) {
397
+ System .err .println ("WARNING: " + processName + " duration exceeded 250 ms! Duration: " + duration + " ms." );
398
+ } else if (duration > 100 ) {
399
+ System .out .println ("NOTICE: " + processName + " duration exceeded 100 ms. Duration: " + duration + " ms." );
400
+ }
401
+ }
318
402
319
403
public static boolean playerExecuted = false ;
320
404
private static BufferedReader minuteFile ;
0 commit comments