gpt4 book ai didi

java - 为什么在 Spring MVC 服务中调用一个简单方法每次都比静态方法慢?

转载 作者:行者123 更新时间:2023-11-30 05:38:19 24 4
gpt4 key购买 nike

在 SpringMVC 服务中进入一个方法并退出该方法花费了太多毫秒。但如果我将方法修改为静态,则只需 1 毫秒。我们的项目是一个SpringMVC-Mybatis项目。我发现 Controller 进入服务方法和退出该方法大约需要70毫秒。该方法从具有 128 个键的静态映射中获取值。

@Controller 
public class OrdersController extends BaseAction
{
@Autowired(required=false)
private CompanyService<Company> companyService;

public void validateInfo()
{
Company company = CompanyService.queryByIdFromCache(account);// cost about 70 milliseconds, but if the method is static it is 1 milliseconds.
}

}

@Service("companyService")
public class CompanyService<T> extends BaseService<T>
{

private static ConcurrentMap<Integer, Company>cache = new ConcurrentHashMap<>(); //map with 128 keys

public Company queryByIdFromCache(Integer id)
{
return cache.get(id);
}
}

我希望该方法在 2 毫秒内完成。该服务以单例模式工作。和companyService是同一个实例。我不想将所有方法都修改为静态方法,因为有些代码必须以非静态方式调用。

最佳答案

很可能某个方面正在拦截对非静态服务方法的调用。

有几种方法可以分析执行情况并找到服务调用的热点。我使用 NetBeans 的 Test Profiler 来重现此问题。

首先,我创建了静态(组件)和非静态服务:

@Service
public class DemoService {

private static final ConcurrentMap<Integer, String> CACHE = new ConcurrentHashMap<>();

public DemoService() {
for (int i = 0; i < 128; i++) {
CACHE.put(i, String.valueOf(i));
}
}

public String queryByIdFromCache(Integer id) {
return CACHE.getOrDefault(id, "");
}

}


public class DemoStaticService {

private static final ConcurrentMap<Integer, String> CACHE = new ConcurrentHashMap<>();


static {
for (int i = 0; i < 128; i++) {
CACHE.put(i, String.valueOf(i));
}
}

public static String queryByIdFromCache(Integer id) {
return CACHE.getOrDefault(id, "");
}

}

然后我创建了一个具有两个操作的 Controller ,一个调用非静态注入(inject)服务,一个调用使用静态方法的服务:

@RestController
@RequestMapping(path = "/demo")
public class DemoController {

@Autowired
private DemoService demoService;

@GetMapping(path = "/demo")
public String callService(@RequestParam Integer id) {
return demoService.queryByIdFromCache(id);
}

@GetMapping(path = "/static-demo")
public String callStaticService(@RequestParam Integer id) {
return DemoStaticService.queryByIdFromCache(id);
}

}

之后,我编写了两个单元测试来帮助我分析服务方法:

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoControllerTest {

@Autowired
private DemoController demoController;

@Before
public void before() {
demoController.callService(1);
demoController.callStaticService(1);
}

@Test
public void testCallService() {
for (int id = 0; id < 128; id++) {
demoController.callService(id);
}
}

@Test
public void testCallStaticService() {
for (int id = 0; id < 128; id++) {
demoController.callStaticService(id);
}
}

}

当测试文件打开时,我选择了配置文件 -> 配置文件测试文件菜单项:

Profile Test File

然后从▶ Profile下拉列表中,我选择了Methods选项:

Profile Dropdown

最后,我单击 ▶ Profile 按钮来分析测试。我得到了这个结果,这表明调用注入(inject)的服务只比调用静态方法贵 50%:

Profile 1

但是如果第二个方法被某个方面拦截(例如@Transactional)怎么办?

为了测试这一点,我更新了 DemoService 并使其方法具有事务性

@Service
public class DemoService {

private static final ConcurrentMap<Integer, String> CACHE = new ConcurrentHashMap<>();

public DemoService() {
for (int i = 0; i < 128; i++) {
CACHE.put(i, String.valueOf(i));
}
}

@Transactional
public String queryByIdFromCache(Integer id) {
return CACHE.getOrDefault(id, "");
}

}

重新运行测试后,这次我得到了这个分析结果:

Profile 2

可以看出,事务方面使对 DemoService.queryByIdFromCache 的调用速度慢了约 14.5 (10.2/0.708) 倍。

要找到服务方法速度缓慢的根本原因,我建议您设置类似的测试并使用 NetBeans Profiler(或类似的工具)对其进行分析。

关于java - 为什么在 Spring MVC 服务中调用一个简单方法每次都比静态方法慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56197461/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com