Skip to content

Commit

Permalink
Make entity in forced chunk periodic check period a power of two to a…
Browse files Browse the repository at this point in the history
…llow for fast modulus. Very minor performance boost. Add CPU utilisation profiling.

Signed-off-by: Ross Allan <rallanpcl@gmail.com>
  • Loading branch information
LunNova committed Jul 18, 2013
1 parent fe16b30 commit ac2b80d
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/common/nallar/patched/world/PatchWorld.java
Expand Up @@ -361,7 +361,7 @@ public void updateEntityWithOptionalForce(Entity entity, boolean notForced) {
}
int x = MathHelper.floor_double(entity.posX);
int z = MathHelper.floor_double(entity.posZ);
boolean periodicUpdate = forcedUpdateCount++ % 19 == 0;
boolean periodicUpdate = forcedUpdateCount++ % 32 == 0;
Boolean isForced_ = entity.isForced;
if (isForced_ == null || periodicUpdate) {
entity.isForced = isForced_ = getPersistentChunks().containsKey(new ChunkCoordIntPair(x >> 4, z >> 4));
Expand Down
Expand Up @@ -11,6 +11,7 @@
import nallar.tickthreading.minecraft.profiling.EntityTickProfiler;
import nallar.tickthreading.minecraft.profiling.PacketProfiler;
import nallar.tickthreading.minecraft.profiling.Timings;
import nallar.tickthreading.minecraft.profiling.UtilisationProfiler;
import nallar.tickthreading.minecraft.tickregion.TickRegion;
import nallar.tickthreading.util.TableFormatter;
import net.minecraft.command.ICommandSender;
Expand Down Expand Up @@ -52,6 +53,11 @@ public void processCommand(final ICommandSender commandSender, List<String> argu
ContentionProfiler.profile(commandSender, 240, 11);
return;
}
if ("u".equals(arguments.get(0))) {
sendChat(commandSender, "Performing CPU utilisation profiling for 1 minute.");
UtilisationProfiler.profile(commandSender, 60);
return;
}
entity_ = "e".equals(arguments.get(0));
if ("c".equals(arguments.get(0))) {
entity_ = true;
Expand All @@ -71,7 +77,7 @@ public void processCommand(final ICommandSender commandSender, List<String> argu
}
}
} catch (Exception e) {
sendChat(commandSender, "Usage: /profile [type=a/e/p/(c [chunk x] [chunk z])] [time=7] [dimensionid=current dimension]");
sendChat(commandSender, "Usage: /profile [type=a/e/l/p/u/(c [chunk x] [chunk z])] [time=7] [dimensionid=current dimension]");
return;
}
final int time = time_;
Expand Down
@@ -0,0 +1,90 @@
package nallar.tickthreading.minecraft.profiling;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.google.common.primitives.Longs;

import nallar.tickthreading.Log;
import nallar.tickthreading.minecraft.commands.Command;
import nallar.tickthreading.util.CollectionsUtil;
import nallar.tickthreading.util.TableFormatter;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;

public class UtilisationProfiler {
public static void profile(final ICommandSender commandSender, int seconds) {
final UtilisationProfiler contentionProfiler = new UtilisationProfiler(seconds);
contentionProfiler.run(new Runnable() {
@Override
public void run() {
TableFormatter tf = new TableFormatter(commandSender);
contentionProfiler.dump(tf, commandSender instanceof MinecraftServer ? 15 : 6);
Command.sendChat(commandSender, tf.toString());
}
});
}

public UtilisationProfiler(int seconds) {
this.seconds = seconds;
}

private final int seconds;
private final Map<String, Long> monitorMap = new HashMap<String, Long>();

public void run(final Runnable completed) {
new Thread(new Runnable() {
@Override
public void run() {
profile();
completed.run();
}
}, "Contention Profiler").start();
}

public void dump(final TableFormatter tf, int entries) {

tf
.heading("Thread")
.heading("Used CPU Time");
for (String key : CollectionsUtil.sortedKeys(monitorMap, entries)) {
tf
.row(key)
.row(monitorMap.get(key) / TimeUnit.SECONDS.toNanos(1));
}
tf.finishTable();
}

private void profile() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
threadMXBean.setThreadCpuTimeEnabled(true);
List<Long> threads = new ArrayList<Long>();
for (Thread thread : Thread.getAllStackTraces().keySet()) {
threads.add(thread.getId());
}
final long[] threads1 = Longs.toArray(threads);
try {
Thread.sleep(seconds * TimeUnit.SECONDS.toMillis(1));
for (long threadId : threads1) {
long time = threadMXBean.getThreadCpuTime(threadId);
if (time < 0) {
continue;
}
ThreadInfo thread = threadMXBean.getThreadInfo(threadId, 0);
if (thread != null) {
monitorMap.put(thread.getThreadName(), time);
}
}
} catch (InterruptedException e) {
Log.severe("Interrupted in profiling", e);
} finally {
threadMXBean.setThreadCpuTimeEnabled(false);
}
}
}

0 comments on commit ac2b80d

Please sign in to comment.