我有一个Java REST应用程序,其中一个端点始终处理=
。我正在进行负载测试,当负载测试开始增加时真的很糟糕。
我可以实施哪些策略来提高应用程序的效率?
我应该使用Jetty线程吗,因为它是我正在使用的服务器?还是主要是代码?还是两者都有?
成为瓶颈的方法如下。
基本上,我需要从给定文件中读取一些行。我无法将其存储在数据库中,因此我通过Map进行了此处理。但是,我知道对于大文件,不仅要花很长时间才能上线,而且我冒这样一个事实,那就是Map包含很多条目时会占用大量内存...
ConcurrentMap
是dict
。
ConcurrentMap
答案 0 :(得分:1)
将ConcurrentMap
与synchronized(this)
混合可能不是正确的方法。 java.util.concurrent
包中的类是为特定用例设计的,并尝试在内部优化同步。
相反,我建议首先尝试一个设计良好的缓存库,看看性能是否足够好。一个示例是Caffeine。根据{{3}}文档,它为您提供了一种声明如何甚至异步加载数据的方法:
AsyncLoadingCache<Key, Graph> cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(10, TimeUnit.MINUTES)
// Either: Build with a synchronous computation that is wrapped as asynchronous
.buildAsync(key -> createExpensiveGraph(key));
// Or: Build with a asynchronous computation that returns a future
.buildAsync((key, executor) -> createExpensiveGraphAsync(key, executor));
答案 1 :(得分:1)
此解决方案基于ConcurrentHashMap#computeIfAbsent,有两个假设:
IllegalArgumentException
。使用此方法,通过将其作为放置密钥所需的计算,我们每个密钥仅打开一次文件。
public String getLine(int lineNr) throws IllegalArgumentException {
if (lineNr > nrLines) {
throw new IllegalArgumentException();
}
return cache.computeIfAbsent(lineNr, (l) -> {
try (Stream<String> st = Files.lines(path)) {
Optional<String> optionalLine = st.skip(lineNr - 1).findFirst();
if (optionalLine.isPresent()) {
return optionalLine.get();
} else {
nrLines = nrLines > lineNr ? lineNr : nrLines;
throw new IllegalArgumentException();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
});
}
我通过产生3个线程来“验证”第二个假设,其中:
尝试一下,也许能奏效,或者假设是错误的,那就太糟糕了。地图内部使用存储桶,因此即使锁定了不同的键,计算也可能成为瓶颈,因为它会锁定存储桶/条带。