1+ package cc .cassian .raspberry .util ;
2+
3+ import cc .cassian .raspberry .config .ModConfig ;
4+ import net .minecraft .client .Minecraft ;
5+ import org .slf4j .Logger ;
6+ import org .slf4j .LoggerFactory ;
7+ import java .io .BufferedWriter ;
8+ import java .io .File ;
9+ import java .io .FileWriter ;
10+ import java .io .IOException ;
11+ import java .time .LocalDateTime ;
12+ import java .time .format .DateTimeFormatter ;
13+ import java .util .Comparator ;
14+ import java .util .LinkedHashMap ;
15+ import java .util .Map ;
16+ import java .util .TreeMap ;
17+
18+ public class RaspberryProfiler {
19+ private static final Logger LOGGER = LoggerFactory .getLogger ("RaspberryProfiler" );
20+ public static final ThreadLocal <Long > TAB_START_TIME = ThreadLocal .withInitial (() -> 0L );
21+
22+ private static final Map <String , Long > creativeTabTimes = new LinkedHashMap <>();
23+ private static final Map <String , Long > emiPluginTimes = new LinkedHashMap <>();
24+ private static final Map <String , Long > searchIndexTimes = new TreeMap <>();
25+
26+ public static void recordCreativeTab (String tabName , long nanos ) {
27+ if (ModConfig .get ().enableProfiler ) {
28+ creativeTabTimes .put (tabName , nanos );
29+ }
30+ }
31+
32+ public static void recordEmiPlugin (String pluginName , long nanos ) {
33+ if (ModConfig .get ().enableProfiler ) {
34+ emiPluginTimes .put (pluginName , nanos );
35+ }
36+ }
37+
38+ public static void recordSearchIndex (String modId , long nanos ) {
39+ if (ModConfig .get ().enableProfiler ) {
40+ searchIndexTimes .merge (modId , nanos , Long ::sum );
41+ }
42+ }
43+
44+ public static void dumpLogs () {
45+ if (!ModConfig .get ().enableProfiler ) return ;
46+
47+ File logDir = new File (Minecraft .getInstance ().gameDirectory , "logs" );
48+ if (!logDir .exists ()) logDir .mkdirs ();
49+ File logFile = new File (logDir , "raspberry_profiler.log" );
50+
51+ try (BufferedWriter writer = new BufferedWriter (new FileWriter (logFile ))) {
52+ writer .write ("Raspberry Core Profiler Log - " + LocalDateTime .now ().format (DateTimeFormatter .ISO_LOCAL_DATE_TIME ));
53+ writer .newLine ();
54+ writer .write ("==================================================" );
55+ writer .newLine ();
56+
57+ writer .write ("--- Creative Mode Tabs Rebuild ---" );
58+ writer .newLine ();
59+ long totalTabTime = 0 ;
60+ creativeTabTimes .entrySet ().stream ()
61+ .sorted (Map .Entry .comparingByValue (Comparator .reverseOrder ()))
62+ .forEach (entry -> writeEntry (writer , entry .getKey (), entry .getValue ()));
63+
64+ for (Long val : creativeTabTimes .values ()) totalTabTime += val ;
65+ writer .write (String .format ("TOTAL TAB TIME: %.2f ms" , totalTabTime / 1_000_000.0 ));
66+ writer .newLine ();
67+ writer .newLine ();
68+
69+ writer .write ("--- Search Tree Indexing (Total) ---" );
70+ writer .newLine ();
71+ searchIndexTimes .forEach ((key1 , value1 ) -> writeEntry (writer , key1 , value1 ));
72+ writer .newLine ();
73+
74+ writer .write ("--- EMI Plugin Loading (Total) ---" );
75+ writer .newLine ();
76+ emiPluginTimes .forEach ((key , value ) -> writeEntry (writer , key , value ));
77+ writer .newLine ();
78+
79+ LOGGER .info ("Dumped profiling info to {}" , logFile .getAbsolutePath ());
80+
81+ } catch (IOException e ) {
82+ LOGGER .error ("Failed to dump Raspberry Profiler logs" , e );
83+ }
84+ }
85+
86+ private static void writeEntry (BufferedWriter writer , String name , long nanos ) {
87+ try {
88+ double ms = nanos / 1_000_000.0 ;
89+ writer .write (String .format ("[%s]: %.2f ms" , name , ms ));
90+ writer .newLine ();
91+ } catch (IOException e ) {
92+ e .printStackTrace ();
93+ }
94+ }
95+ }
0 commit comments