Springframework';s InvocableHandlerMethod.GetMethodArgumentValue占用大量cpu

Springframework';s InvocableHandlerMethod.GetMethodArgumentValue占用大量cpu,spring,Spring,我有一个用java和Spring4.0编写的web应用程序,部署在tomcat(RedHatLinux)上。在使用JProfiler评测我们的webapp时,我们发现大部分时间都花在Springframework中,这导致了API的速度减慢。例如,考虑下面提到的数据,显示在614秒内,在Spring中花了609秒,这是用于105个API调用,这意味着每个API调用的时间是6秒。 所以我想知道spring中是否有可以避免这种开销的配置 编辑:添加我使用JProfiler获得的更多数据 91.0

我有一个用java和Spring4.0编写的web应用程序,部署在tomcat(RedHatLinux)上。在使用JProfiler评测我们的webapp时,我们发现大部分时间都花在Springframework中,这导致了API的速度减慢。例如,考虑下面提到的数据,显示在614秒内,在Spring中花了609秒,这是用于105个API调用,这意味着每个API调用的时间是6秒。 所以我想知道spring中是否有可以避免这种开销的配置

编辑:添加我使用JProfiler获得的更多数据

  91.0% - 614 s org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest 
        90.2% - 609 s org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues
            55.9% - 377 s org.springframework.validation.DataBinder.convertIfNecessary
            34.2% - 231 s org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.resolveName
        0.8% - 5,709 ms org.springframework.web.method.support.InvocableHandlerMethod.invoke
编辑: 进一步深入研究后,我发现,在这90.2%的时间中,有88%被以下两种方法消耗

  org.springframework.util.ConcurrentReferenceHashMap.put
  org.springframework.util.ConcurrentReferenceHashMap.get
而且他们是从 org.springframework.core.ResolvableType.forType

有人在linux和Spring应用程序上也观察到了这一点吗


仅供参考我的控制器方法有23个查询参数,其中9个是列表,这会产生任何问题吗?我不应该有这么多的查询参数(@RequestParam)?

park
不会执行繁忙的等待。实际上,它甚至不知道线程正在等待的条件。这取决于打电话的人。但是,如果经常调用
park
,例如调用了
unpark
,但在重新检查等待条件后,会再次调用
park
,则仍然会消耗大量CPU。然后,
park
的固定开销将累积


因此,这里的情况似乎是,您在某个特定锁上存在严重的争用。从您发布的堆栈跟踪中,我猜
ConcurrentReferenceHashMap
配置的并发级别远远小于您的实际线程数。

似乎是自定义参数解析器完成了这一任务。如中所述创建一个后


jprofiler计时很好,而且我的customArgumentResolver消耗的CPU没有HandlerMethodArgumentResolverComposite.resolveArgument多 他在做什么


现在额外的90.2%的时间减少到了2%(10秒)

我同意,这就是我在问题中观察到和写的,调用方方法java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued循环并一次又一次调用park,直到成功,所以它的acquireQueued正在进行繁忙等待。将问题标题更改为具有误导性。Thanks@Rahul:但AQS不执行“忙等待”,因为它调用
park
park
将释放CPU。但据我所知,os_linux.cpp中的park实现不会释放CPU,因为它使用的是pthread_mutex_trylock(mutex),如果失败(因为其他人已经获得了该互斥体),它将立即从那里返回,AQS将在其for(;)中再次调用park环下面是代码段//如果无法获得锁,请不要等待,因为取消阻止会产生干扰。也。如果(Thread::is_interrupted(Thread,false)| | pthread_mutex_trylock(_mutex)!=0){return;}只有在另一个线程同时调用
unpark
时才会发生这种情况,请在尝试等待之前检查中断。但无论如何,你看错地方了。如前所述,重要的不是
park
的实现,而是这么多线程都在争夺同一个锁。