1+ package io .github .milkdrinkers .colorparser .common ;
2+
3+ import io .github .milkdrinkers .colorparser .common .mock .MockComponentBuilder ;
4+ import io .github .milkdrinkers .colorparser .common .mock .engine .MockParserEngine ;
5+ import io .github .milkdrinkers .colorparser .common .mock .engine .MockParserEngineBuilder ;
6+ import net .kyori .adventure .text .Component ;
7+ import net .kyori .adventure .text .minimessage .tag .resolver .Placeholder ;
8+ import net .kyori .adventure .text .minimessage .tag .resolver .TagResolver ;
9+ import org .openjdk .jmh .annotations .*;
10+ import org .openjdk .jmh .infra .Blackhole ;
11+
12+ import java .util .ArrayList ;
13+ import java .util .List ;
14+
15+ @ SuppressWarnings ("unused" )
16+ @ State (Scope .Benchmark )
17+ public class ComponentBuilderBenchmark {
18+ private static final String SIMPLE_CONTENT = "<red>Hello <bold>World</bold></red>" ;
19+ private static final String COMPLEX_CONTENT = "<gradient:red:blue>Complex <hover:show_text:'<green>Tooltip</green>'>hover text</hover> with <click:run_command:'/test'>click</click> and <player_name> placeholder</gradient>" ;
20+ private static final String LEGACY_CONTENT = "&cRed &lBold &r&9Blue &o&nUnderlined" ;
21+
22+ private MockParserEngine engine ;
23+ private MockComponentBuilder reusableBuilder ;
24+ private List <TagResolver > tagResolvers ;
25+
26+ @ Setup (Level .Trial )
27+ public void setupTrial () {
28+ engine = new MockParserEngineBuilder ().build ();
29+ reusableBuilder = engine .parse (SIMPLE_CONTENT );
30+
31+ // Pre-create tag resolvers for TagResolver benchmark
32+ tagResolvers = new ArrayList <>();
33+ for (int i = 0 ; i < 20 ; i ++) {
34+ tagResolvers .add (Placeholder .parsed ("tag_" + i , "<color:#ff" + String .format ("%04x" , i ) + ">Tag " + i + "</color>" ));
35+ }
36+ }
37+
38+ @ Benchmark
39+ public Component benchmarkSimpleComponentBuilding () {
40+ final MockComponentBuilder b = engine .parse (SIMPLE_CONTENT );
41+ return b .build ();
42+ }
43+
44+ @ Benchmark
45+ public Component benchmarkComplexComponentWithPlaceholders () {
46+ final MockComponentBuilder b = engine .parse (COMPLEX_CONTENT );
47+ return b .with ("player_name" , "<gold>TestPlayer</gold>" )
48+ .with ("server_name" , "<blue>TestServer</blue>" )
49+ .with ("timestamp" , "<gray>2025-06-12</gray>" )
50+ .build ();
51+ }
52+
53+ @ Benchmark
54+ public Component benchmarkLegacyColorProcessing () {
55+ final MockComponentBuilder b = engine .parse (LEGACY_CONTENT );
56+ return b .legacy ().build ();
57+ }
58+
59+ @ Benchmark
60+ public Component benchmarkBuilderReuse () {
61+ reusableBuilder .with ("test1" , "value1" ).build ();
62+ return reusableBuilder .with ("test2" , "value2" ).build ();
63+ }
64+
65+ @ Benchmark
66+ public Component benchmarkMemoryAllocation (Blackhole bh ) {
67+ final List <Component > components = new ArrayList <>();
68+
69+ for (int i = 0 ; i < 100 ; i ++) {
70+ final MockComponentBuilder b = engine .parse ("<red>" + i + "</red>" );
71+ Component component = b .build ();
72+ components .add (component );
73+ bh .consume (component );
74+ }
75+
76+ return components .getLast ();
77+ }
78+
79+ @ Benchmark
80+ public Component benchmarkTagResolvers () {
81+ final MockComponentBuilder b = engine .parse (generateContentWithTags (20 ));
82+ tagResolvers .forEach (b ::tag );
83+ return b .build ();
84+ }
85+
86+ @ State (Scope .Benchmark )
87+ public static class PlaceholderState {
88+ @ Param ({"1" , "5" , "10" , "25" , "50" , "100" })
89+ public int placeholderCount ;
90+
91+ public MockParserEngine engine ;
92+ public String content ;
93+
94+ @ Setup (Level .Trial )
95+ public void setup () {
96+ engine = new MockParserEngineBuilder ().build ();
97+ content = generateContentWithPlaceholders (placeholderCount );
98+ }
99+ }
100+
101+ @ Benchmark
102+ public Component benchmarkScalingWithPlaceholders (PlaceholderState state ) {
103+ final MockComponentBuilder b = state .engine .parse (state .content );
104+
105+ for (int i = 0 ; i < state .placeholderCount ; i ++) {
106+ b .with ("placeholder_" + i , "<color:#" + String .format ("%06x" , i * 1000 ) + ">Value " + i + "</color>" );
107+ }
108+
109+ return b .build ();
110+ }
111+
112+ private static String generateContentWithPlaceholders (int count ) {
113+ final StringBuilder sb = new StringBuilder ("<gradient:red:blue>" );
114+ for (int i = 0 ; i < count ; i ++) {
115+ sb .append ("<placeholder_" ).append (i ).append ("> " );
116+ }
117+ sb .append ("</gradient>" );
118+ return sb .toString ();
119+ }
120+
121+ @ SuppressWarnings ("SameParameterValue" )
122+ private static String generateContentWithTags (int count ) {
123+ final StringBuilder sb = new StringBuilder ();
124+ for (int i = 0 ; i < count ; i ++) {
125+ sb .append ("<tag_" ).append (i ).append ("> " );
126+ }
127+ return sb .toString ();
128+ }
129+ }
0 commit comments