Skip to content

Commit 6a38146

Browse files
committed
🔧 Sincronizar sistema de cache completo
- Añadir paquete io.warmup.framework.cache completo - Actualizar .gitignore para permitir cache del framework - Incluir ASMCacheManager, CacheConfig y ReflectionCache - Sistema de cache JIT completamente funcional
1 parent 47a395f commit 6a38146

4 files changed

Lines changed: 905 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@
816816
# ==============================================================================
817817
**/.cache/
818818
**/cache/
819+
!**warmup-core/src/main/java/io/warmup/framework/cache/
819820
**/build/
820821
**/dist/
821822
**/out/
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
package io.warmup.framework.cache;
2+
3+
import java.io.Serializable;
4+
import java.security.MessageDigest;
5+
import java.util.concurrent.ConcurrentHashMap;
6+
import java.util.concurrent.ConcurrentMap;
7+
import java.util.logging.Level;
8+
import java.util.logging.Logger;
9+
10+
/**
11+
* ASM Cache Manager para el framework Warmup.
12+
* Gestiona el cache de bytecode generado por ASM para optimizar el rendimiento JIT.
13+
*
14+
* @author MiniMax Agent
15+
* @since 2.0
16+
*/
17+
public class ASMCacheManager implements Serializable {
18+
19+
private static final Logger log = Logger.getLogger(ASMCacheManager.class.getName());
20+
private static final long serialVersionUID = 1L;
21+
22+
private static ASMCacheManager instance;
23+
24+
// Cache principal: cacheKey -> CacheEntry
25+
private final ConcurrentMap<String, CacheEntry> bytecodeCache;
26+
27+
// Estadísticas del cache
28+
private long hits = 0;
29+
private long misses = 0;
30+
private long entries = 0;
31+
32+
/**
33+
* Constructor privado para patrón Singleton
34+
*/
35+
private ASMCacheManager() {
36+
this.bytecodeCache = new ConcurrentHashMap<>();
37+
log.log(Level.INFO, "ASMCacheManager inicializado");
38+
}
39+
40+
/**
41+
* Obtiene la instancia singleton del ASMCacheManager
42+
*/
43+
public static synchronized ASMCacheManager getInstance() {
44+
if (instance == null) {
45+
instance = new ASMCacheManager();
46+
}
47+
return instance;
48+
}
49+
50+
/**
51+
* Calcula el hash del código fuente original
52+
*/
53+
public String calculateSourceHash(byte[] originalClassData) {
54+
try {
55+
MessageDigest digest = MessageDigest.getInstance("SHA-256");
56+
byte[] hash = digest.digest(originalClassData);
57+
58+
// Convertir a hexadecimal
59+
StringBuilder hexString = new StringBuilder();
60+
for (byte b : hash) {
61+
String hex = Integer.toHexString(0xff & b);
62+
if (hex.length() == 1) {
63+
hexString.append('0');
64+
}
65+
hexString.append(hex);
66+
}
67+
return hexString.toString();
68+
} catch (Exception e) {
69+
log.log(Level.WARNING, "Error calculando hash de fuente: {0}", e.getMessage());
70+
return "error-hash";
71+
}
72+
}
73+
74+
/**
75+
* Obtiene el bytecode cacheado para una clave específica
76+
*/
77+
public byte[] getCachedBytecode(String cacheKey, String sourceHash) {
78+
CacheEntry entry = bytecodeCache.get(cacheKey);
79+
if (entry == null) {
80+
misses++;
81+
return null;
82+
}
83+
84+
// Verificar si el hash coincide (invalidación por cambios en el código fuente)
85+
if (!entry.getSourceHash().equals(sourceHash)) {
86+
bytecodeCache.remove(cacheKey);
87+
entries--;
88+
misses++;
89+
return null;
90+
}
91+
92+
hits++;
93+
log.log(Level.FINE, "Cache HIT para clave: {0}", cacheKey);
94+
return entry.getBytecode();
95+
}
96+
97+
/**
98+
* Guarda bytecode en el cache
99+
*/
100+
public void cacheBytecode(String cacheKey, String sourceHash, byte[] bytecode) {
101+
CacheEntry entry = new CacheEntry(sourceHash, bytecode);
102+
CacheEntry previous = bytecodeCache.put(cacheKey, entry);
103+
if (previous == null) {
104+
entries++;
105+
}
106+
107+
log.log(Level.FINE, "Cache guardado para clave: {0}, entradas totales: {1}",
108+
new Object[]{cacheKey, entries});
109+
}
110+
111+
/**
112+
* Invalida una entrada específica del cache
113+
*/
114+
public void invalidate(String cacheKey) {
115+
CacheEntry removed = bytecodeCache.remove(cacheKey);
116+
if (removed != null) {
117+
entries--;
118+
log.log(Level.FINE, "Entrada invalidada del cache: {0}", cacheKey);
119+
}
120+
}
121+
122+
/**
123+
* Limpia todo el cache
124+
*/
125+
public void clearCache() {
126+
int cleared = bytecodeCache.size();
127+
bytecodeCache.clear();
128+
entries = 0;
129+
log.log(Level.INFO, "Cache limpiado completamente. Entradas eliminadas: {0}", cleared);
130+
}
131+
132+
/**
133+
* Obtiene las estadísticas del cache
134+
*/
135+
public void getStats() {
136+
long total = hits + misses;
137+
double hitRate = total > 0 ? (double) hits / total * 100 : 0;
138+
139+
String stats = String.format(
140+
"ASMCacheManager Stats - Entries: %d, Hits: %d, Misses: %d, Hit Rate: %.2f%%",
141+
entries, hits, misses, hitRate
142+
);
143+
144+
log.log(Level.INFO, stats);
145+
}
146+
147+
/**
148+
* Obtiene estadísticas como objeto para uso programático
149+
*/
150+
public CacheStats getCacheStats() {
151+
long total = hits + misses;
152+
double hitRate = total > 0 ? (double) hits / total * 100 : 0;
153+
154+
return new CacheStats(entries, hits, misses, hitRate);
155+
}
156+
157+
/**
158+
* Clase interna para representar una entrada del cache
159+
*/
160+
private static class CacheEntry implements Serializable {
161+
private static final long serialVersionUID = 1L;
162+
163+
private final String sourceHash;
164+
private final byte[] bytecode;
165+
private final long timestamp;
166+
167+
public CacheEntry(String sourceHash, byte[] bytecode) {
168+
this.sourceHash = sourceHash;
169+
this.bytecode = bytecode;
170+
this.timestamp = System.currentTimeMillis();
171+
}
172+
173+
public String getSourceHash() {
174+
return sourceHash;
175+
}
176+
177+
public byte[] getBytecode() {
178+
return bytecode;
179+
}
180+
181+
public long getTimestamp() {
182+
return timestamp;
183+
}
184+
}
185+
186+
/**
187+
* Clase para representar estadísticas del cache
188+
*/
189+
public static class CacheStats implements Serializable {
190+
private static final long serialVersionUID = 1L;
191+
192+
private final long entries;
193+
private final long hits;
194+
private final long misses;
195+
private final double hitRate;
196+
197+
public CacheStats(long entries, long hits, long misses, double hitRate) {
198+
this.entries = entries;
199+
this.hits = hits;
200+
this.misses = misses;
201+
this.hitRate = hitRate;
202+
}
203+
204+
public long getEntries() {
205+
return entries;
206+
}
207+
208+
public long getHits() {
209+
return hits;
210+
}
211+
212+
public long getMisses() {
213+
return misses;
214+
}
215+
216+
public double getHitRate() {
217+
return hitRate;
218+
}
219+
220+
@Override
221+
public String toString() {
222+
return String.format(
223+
"CacheStats{entries=%d, hits=%d, misses=%d, hitRate=%.2f%%}",
224+
entries, hits, misses, hitRate
225+
);
226+
}
227+
}
228+
}

0 commit comments

Comments
 (0)