Skip to content

Commit c516aa1

Browse files
committed
feat:实现正则表达式编译缓存功能
1 parent 516b0ff commit c516aa1

File tree

3 files changed

+179
-3
lines changed

3 files changed

+179
-3
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.taobao.arthas.core.util;
2+
3+
import com.taobao.arthas.core.shell.term.impl.http.session.LRUCache;
4+
import java.util.regex.Pattern;
5+
6+
/**
7+
* 正则表达式缓存管理器
8+
* 用于缓存编译后的正则表达式对象,避免重复编译的开销
9+
*/
10+
public class RegexCacheManager {
11+
private static final RegexCacheManager INSTANCE = new RegexCacheManager();
12+
13+
// 使用 LRUCache 替代 ConcurrentHashMap
14+
private final LRUCache<String, Pattern> regexCache;
15+
16+
// 缓存大小限制
17+
private static final int MAX_CACHE_SIZE = 100;
18+
19+
private RegexCacheManager() {
20+
// 初始化 LRUCache,设置最大缓存大小
21+
this.regexCache = new LRUCache<>(MAX_CACHE_SIZE);
22+
}
23+
24+
public static RegexCacheManager getInstance() {
25+
return INSTANCE;
26+
}
27+
28+
/**
29+
* 获取正则表达式Pattern对象,优先从缓存获取,缓存未命中则编译并缓存
30+
*/
31+
public Pattern getPattern(String regex) {
32+
if (regex == null || regex.isEmpty()) {
33+
return null;
34+
}
35+
36+
// 从 LRUCache 获取
37+
Pattern pattern = regexCache.get(regex);
38+
if (pattern != null) {
39+
return pattern;
40+
}
41+
42+
// 缓存未命中,编译正则表达式
43+
pattern = Pattern.compile(regex);
44+
45+
// 缓存编译结果
46+
regexCache.put(regex, pattern);
47+
48+
return pattern;
49+
}
50+
51+
/**
52+
* 清理缓存
53+
*/
54+
public void clearCache() {
55+
regexCache.clear();
56+
}
57+
58+
/**
59+
* 获取缓存大小
60+
*/
61+
public int getCacheSize() {
62+
return regexCache.usedEntries();
63+
}
64+
65+
}
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
package com.taobao.arthas.core.util.matcher;
22

3+
import com.taobao.arthas.core.util.RegexCacheManager;
4+
import java.util.regex.Pattern;
5+
36
/**
47
* regex matcher
58
* @author ralf0131 2017-01-06 13:16.
69
*/
710
public class RegexMatcher implements Matcher<String> {
811

9-
private final String pattern;
12+
private final Pattern pattern;
1013

1114
public RegexMatcher(String pattern) {
12-
this.pattern = pattern;
15+
// 使用正则表达式缓存
16+
this.pattern = RegexCacheManager.getInstance().getPattern(pattern);
1317
}
1418

1519
@Override
1620
public boolean matching(String target) {
1721
return null != target
1822
&& null != pattern
19-
&& target.matches(pattern);
23+
&& pattern.matcher(target).matches();
2024
}
2125
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.taobao.arthas.core.util;
2+
3+
import org.junit.Assert;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
7+
import java.util.regex.Pattern;
8+
9+
/**
10+
* RegexCacheManager测试类
11+
*/
12+
public class RegexCacheManagerTest {
13+
private RegexCacheManager cacheManager;
14+
15+
@Before
16+
public void setUp() {
17+
// 获取单例实例
18+
cacheManager = RegexCacheManager.getInstance();
19+
// 清理缓存,确保测试环境干净
20+
cacheManager.clearCache();
21+
}
22+
23+
/**
24+
* 测试基本缓存功能
25+
*/
26+
@Test
27+
public void testBasicCacheFunctionality() {
28+
// 测试缓存未命中的情况
29+
String regex1 = ".*Test.*";
30+
Pattern pattern1 = cacheManager.getPattern(regex1);
31+
Assert.assertNotNull(pattern1);
32+
Assert.assertEquals(1, cacheManager.getCacheSize());
33+
34+
// 测试缓存命中的情况
35+
Pattern pattern1Cached = cacheManager.getPattern(regex1);
36+
Assert.assertNotNull(pattern1Cached);
37+
Assert.assertSame(pattern1, pattern1Cached); // 应该是同一个对象
38+
Assert.assertEquals(1, cacheManager.getCacheSize()); // 缓存大小应该保持不变
39+
40+
// 测试多个正则表达式
41+
String regex2 = "^Test.*";
42+
Pattern pattern2 = cacheManager.getPattern(regex2);
43+
Assert.assertNotNull(pattern2);
44+
Assert.assertEquals(2, cacheManager.getCacheSize());
45+
46+
// 测试空正则表达式
47+
Pattern nullPattern = cacheManager.getPattern(null);
48+
Assert.assertNull(nullPattern);
49+
50+
Pattern emptyPattern = cacheManager.getPattern("");
51+
Assert.assertNull(emptyPattern);
52+
}
53+
54+
/**
55+
* 测试LRU淘汰策略
56+
*/
57+
@Test
58+
public void testLRUEvictionPolicy() {
59+
// 生成多个正则表达式,超过最大缓存大小
60+
int maxCacheSize = 100;
61+
for (int i = 0; i < maxCacheSize + 5; i++) {
62+
String regex = "TestRegex" + i;
63+
Pattern pattern = cacheManager.getPattern(regex);
64+
Assert.assertNotNull(pattern);
65+
}
66+
67+
// 缓存大小应该等于最大缓存大小
68+
Assert.assertTrue(cacheManager.getCacheSize() <= 100); // 100 是实际的最大缓存大小
69+
70+
// 测试访问顺序,确保 LRU 策略生效
71+
String firstRegex = "TestRegex0";
72+
73+
// 再次访问第一个正则表达式,使其成为最近使用的
74+
Pattern firstPattern = cacheManager.getPattern(firstRegex);
75+
Assert.assertNotNull(firstPattern);
76+
77+
// 再添加一个新的正则表达式,应该淘汰最久未使用的
78+
String newRegex = "NewTestRegex";
79+
Pattern newPattern = cacheManager.getPattern(newRegex);
80+
Assert.assertNotNull(newPattern);
81+
82+
// 第一个正则表达式应该仍然在缓存中(因为刚被访问过)
83+
Pattern firstPatternAgain = cacheManager.getPattern(firstRegex);
84+
Assert.assertNotNull(firstPatternAgain);
85+
}
86+
87+
/**
88+
* 测试缓存清理功能
89+
*/
90+
@Test
91+
public void testCacheClear() {
92+
// 添加一些缓存项
93+
cacheManager.getPattern(".*Test1");
94+
cacheManager.getPattern(".*Test2");
95+
Assert.assertTrue(cacheManager.getCacheSize() > 0);
96+
97+
// 清理缓存
98+
cacheManager.clearCache();
99+
Assert.assertEquals(0, cacheManager.getCacheSize());
100+
101+
// 清理后应该可以重新添加缓存项
102+
Pattern pattern = cacheManager.getPattern(".*Test3");
103+
Assert.assertNotNull(pattern);
104+
Assert.assertEquals(1, cacheManager.getCacheSize());
105+
}
106+
107+
}

0 commit comments

Comments
 (0)