java - 톰캣 구동 속도




글로벌 Tomcat/JVM 속도 저하의 원인은 무엇입니까? (5)

누군가 어디서 볼지 생각 했습니까?

  1. Tomcat / JVM에서 문제가 발생할 수 있습니다. 일반적인 데이터베이스와 같은 공유 리소스를 사용하는 몇 가지 일괄 작업이 있습니까?

  2. 응용 프로그램 응답 시간이 폭발 할 때 스레드 덤프를 취하고 Java 프로세스가 수행중인 작업을 확인하십시오.

  3. Linux를 사용하는 경우 strace 와 같은 도구를 사용하여 java 프로세스가 수행중인 작업을 확인하십시오.

Tomcat 7 / Java 7에서 Java EE-ish 웹 응용 프로그램 (Hibernate 4 + Spring + Quartz + JSF + Facelets + Richfaces)의 여러 인스턴스 (약 15 개)를 실행하면서 이상하지만 심각한 문제가 발생했습니다.

시스템은 정상적으로 작동하지만 시간이 크게 변한 후에 동시에 모든 응용 프로그램 인스턴스가 갑자기 응답 시간이 증가합니다. 기본적으로 애플리케이션은 여전히 ​​작동하지만 응답 시간은 약 3 배 더 높습니다.

이것은 두 개의 특정 워크 플로우 / 액션 (로그인, 세미나 액세스 목록,이 목록 새로 고침, 로그 아웃, 두 번째 줄은 아약스 새로 고침의 요청 시간)과 두 개의 짧은 워크 플로 / 액션의 응답 시간을 표시하는 두 개의 다이어그램입니다 응용 프로그램 :

두 응용 프로그램의 인스턴스가 동시에 폭발하면서 "느리게"볼 수 있습니다. 서버를 다시 시작하면 모든 것이 정상으로 돌아갑니다. 응용 프로그램의 모든 인스턴스가 동시에 "폭발"합니다.

세션 데이터를 데이터베이스에 저장하고이를 클러스터링에 사용합니다. 우리는 세션 크기와 번호를 확인했는데 둘 다 낮습니다 (다른 응용 프로그램이있는 다른 서버에서 우리는 더 크고 더 많은 세션을 가끔 있음). 클러스터에있는 다른 톰캣은 보통 몇 시간 더 빠르게 머물러 있으며,이 랜덤 틱 시간 후에도 "죽는다". jconsole을 사용하여 힙 크기를 확인했으며 주 힙 크기는 2.5 - 1GB 사이 였고 db 연결 풀은 기본적으로 무료 연결과 스레드 풀로 가득차 있습니다. 최대 힙 크기는 5GB이고 사용 가능한 perm 공간도 충분합니다. 부하가 특별히 높지는 않습니다. 메인 CPU에 약 5 %의 부하 만 있습니다. 서버가 스왑되지 않습니다. 문제가 똑같은 VM에 응용 프로그램을 추가로 배포 했으므로 하드웨어 문제도 발생하지 않습니다.

나는 더 이상 볼 곳이 어디인지 모르겠다. 나는 생각이 없다. 누군가 어디서 볼지 생각 했습니까?

2013-02-21 업데이트 : 새로운 데이터!

애플리케이션에 타이밍 추적을 두 개 더 추가했습니다. 측정과 관련하여 모니터링 시스템은 두 가지 작업을 수행하는 서블릿을 호출하고 서버에서 각 서버의 실행 시간을 측정 한 후 응답으로 소요 된 시간을 기록합니다. 이 값은 모니터링 시스템에 의해 기록됩니다.

흥미로운 몇 가지 새로운 사실이 있습니다. 애플리케이션을 빠르게 재배포하면 현재 Tomcat의 단일 인스턴스가 실행됩니다. 이것은 또한 원시 CPU 계산 성능에 영향을 미치는 것 같습니다 (아래 참조). 이 개인 - 상황 - 폭발은 무작위로 발생하는 전체 - 상황 - 폭발과는 다르다.

이제 일부 데이터의 경우 :

먼저 개별 라인 :

  1. 연한 파란색은 작은 워크 플로우의 전체 실행 시간입니다 (자세한 내용은 위 참조). 클라이언트에서 측정
  2. 빨간색은 밝은 파란색의 "부분"이며 클라이언트에서 측정 된 해당 워크 플로우의 특별한 단계를 수행하는 데 걸린 시간입니다
  3. 진한 파란색은 응용 프로그램에서 측정되며 최대 절전 모드를 통해 DB에서 엔티티 목록을 읽은 다음 해당 목록을 반복하여 지연 컬렉션 및 지연 엔티티를 가져 오는 것으로 구성됩니다.
  4. 녹색은 부동 소수점 및 정수 연산을 사용하는 작은 CPU 벤치 마크입니다. 멀리 객체 할당을 참조하십시오, 그래서 아무 쓰레기도.

이제 폭발의 각 단계마다 : 나는 각 이미지에 3 개의 검은 색 점으로 표시했다. 첫 번째 것은 하나 또는 그 이상의 애플리케이션 인스턴스에서 "작은"explostion입니다. Inst1에서 점프 (특히 빨간색 선에서 볼 수 있음)하는 반면 Inst2는 다소 침착하게 유지됩니다.

이 작은 폭발 후에 "빅뱅"이 발생하고 Tomcat의 모든 응용 프로그램 인스턴스가 폭발합니다 (두 번째 점). 이 폭발은 CPU 벤치 마크가 아닌 모든 상위 레벨 조작 (요청 처리, DB 액세스)에 영향을줍니다. 두 시스템 모두 낮게 유지됩니다.

그 후 context.xml 파일을 터치하여 Inst1을 핫 전개했다. 내가 전에 말했듯이,이 경우는 폭발에서 지금까지 완전히 황폐화되었습니다 (밝은 파란색 선은 도표에서 벗어났습니다 - 약 18 초). a)이 재배치가 Inst2에 전혀 영향을 미치지 않고 b) Inst1의 원시 DB 액세스에도 영향을 미치지 않는 방법 - CPU가 갑자기 느려진 것처럼 보입니다! . 이것은 미친 짓입니다.

업데이트 업데이트 Tomcat의 누출 방지 리스너는 응용 프로그램을 배포 취소 할 때 오래된 ThreadLocals 또는 Threads에 대해 우회하지 않습니다. 분명히 클린업 문제가있는 것 같습니다 (빅뱅과 직접적인 관련이 없다고 가정하고 있습니다). 그러나 Tomcat은 나에게 힌트가 없습니다.

2013-02-25 업데이트 : 애플리케이션 환경 및 석영 일정

응용 프로그램 환경은 그다지 정교하지 않습니다. 네트워크 구성 요소는 제쳐두고 (기본적으로는 알지 못합니다) 기본적으로 하나의 응용 프로그램 서버 (Linux)와 두 개의 데이터베이스 서버 (MySQL 5 및 MSSQL 2008)가 있습니다. 주로드는 MSSQL 서버에 있고 다른 세션은 세션을 저장하는 장소로 사용됩니다.

응용 프로그램 서버는 두 Tomcats 사이에서로드 균형 조정기로 Apache를 실행합니다. 따라서 두 개의 JVM이 동일한 하드웨어 (두 개의 Tomcat 인스턴스 )에서 실행됩니다. 우리는이 구성을 사용하여 응용 프로그램 서버가 응용 프로그램을 올바르게 실행할 수 있기 때문에 (실제로 수년 동안 해왔 던) 부하를 분산시키지 않고 다운 타임없이 작은 응용 프로그램을 업데이트 할 수 있도록했습니다. 문제의 웹 응용 프로그램은 Tomcat 당 약 15 개의 컨텍스트를 사용 하여 서로 다른 고객을 위해 별도의 컨텍스트 로 배포됩니다. (필자는 게시 할 때 "인스턴스"와 "컨텍스트"가 섞여있는 것처럼 보입니다. 사무실에서 그들은 종종 동의어로 사용되며 대개는 동료가 말하는 내용을 마술처럼 알게됩니다. 정말 좋지 않습니다.)

보다 나은 어휘로 상황을 명확히하기 위해 : 게시 한 다이어그램은 동일한 JVM에서 동일한 애플리케이션의 서로 다른 두 컨텍스트의 응답 시간을 표시합니다. Big Bang은 하나의 JVM에있는 모든 컨텍스트에 영향을 미치지 만 다른 하나에서는 발생하지 않습니다 (Tomcat이 임의로 폭발하는 순서는 btw입니다). hot-redeployment 후에 한 Tomcat 인스턴스의 한 컨텍스트는 모든 컨텍스트에 대해 느린 CPU와 같은 모든 재미있는 부작용을 가지고 있습니다.

시스템의 전반적인 부하는 다소 적습니다. 동시에 약 30 명의 활성 사용자가있는 내부 핵심 비즈니스 관련 소프트웨어입니다. 응용 프로그램 별 요청 (서버 접촉)은 현재 분당 약 130입니다. 단일 요청의 수는 적지 만 요청 자체는 종종 데이터베이스에 수백 개의 선택을 요구하기 때문에 비용이 많이 듭니다. 그러나 대개 모든 것이 완벽하게 받아 들여집니다. 또한 응용 프로그램은 큰 무한 캐시를 만들지 않습니다. 일부 조회 데이터는 캐시되지만 짧은 시간 동안 만 캐시됩니다.

위의 필자는 애플리케이션을 실행할 수있는 서버가 수년 동안 괜찮다고 썼다. 문제를 발견 할 수있는 가장 좋은 방법은 문제가 처음으로 잘못되었을 때를 정확히 알아 내고 (애플리케이션 자체, 관련 라이브러리 또는 인프라에서)이 시간대에 변경된 사항을 확인하는 것이지만 문제는 문제가 처음 발생했을 때 우리는 알지 못합니다. 그냥 부차적 인 (부적절한 의미에서) 애플리케이션 모니터링이라고 부르 자. - /

우리는 몇 가지 측면을 배제했지만 지난 몇 개월 동안 응용 프로그램이 여러 번 업데이트되어 예전 버전을 단순히 배포 할 수 없습니다. 기능 변경이 아닌 가장 큰 업데이트는 JSP에서 Facelets 로의 전환이었습니다. 그러나 여전히 "무언가"가 모든 문제의 원인이되어야하지만, Facelets가 순수 DB 쿼리 시간에 영향을 미치는 이유에 대해서는 잘 모릅니다.

석영

석영 일정에 관해서는 총 8 개의 일자리가 있습니다. 대부분은 하루에 한 번만 실행되며 대용량 데이터 동기화 ( "대용량 데이터 대형"과 같이 절대 "크지 않은", 평상시의 일상 작업을 통해 볼 때 일반 사용자보다 훨씬 뛰어납니다)과 관련이 있습니다. 그러나 그 작업은 물론 야간에 실행되며 문제는 주간에 발생합니다. 나는 여기에 detailled 직업 목록을 생략합니다 (나는 더 많은 세부 사항을 제공 할 수 있다면 유익한 경우). 작업의 소스 코드는 지난 몇 개월 동안 변경되지 않았습니다. 폭발물이 일자리와 부합하는지 여부는 이미 확인했지만, 그 결과는 기껏해야 결정적이지 않습니다. 나는 실제로 그들이 정렬하지 않는다고 말하고 싶지만, 매분마다 실행되는 여러 작업들이 있기 때문에 나는 그것을 아직 배제 할 수 없다. 매분마다 실행되는 acutal 작업은 내 생각에 꽤 가볍습니다. 데이터가 다른 소스, DB, 외부 시스템, 전자 메일 계정에서 사용 가능한지 확인한 후 DB에 쓰거나 다른 시스템으로 밀어 넣습니다. .

그러나 현재 개별 작업 실행의 시작 및 종료 타임 스탬프를 볼 수 있도록 개별 작업 실행 로깅을 활성화하고 있습니다. 아마도 이것은 더 많은 통찰력을 제공합니다.

2013-02-28 업데이트 : JSF 단계 및 타이밍

나는 수동으로 JSF phae 리스너를 애플리케이션에 추가했다. 샘플 호출 (Ajax 새로 고침)을 실행했고 이것이 내가 가진 것입니다 (왼쪽 : 정상적인 Tomcat 인스턴스 실행, 오른쪽 : Tomcat 인스턴스, Big Bang 이후 - Tomcats에서 숫자가 거의 동시에 가져 왔고 밀리 초 단위).

  1. RESTORE_VIEW : 17 대 46
  2. APPLY_REQUEST_VALUES : 170 vs 486
  3. 진행 중 : 78 대 321
  4. UPDATE_MODEL_VALUES : 75 대 307
  5. RENDER_RESPONSE : 1059 vs 4162

Ajax 새로 고침 자체는 검색 양식과 검색 결과에 속합니다. 또한 애플리케이션의 최 FlowExecutionListenerAdapter 요청 필터와 웹 플로우 사이에는 또 다른 지연이 있습니다. 웹 플로우의 특정 단계에서 취해진 시간을 측정하는 FlowExecutionListenerAdapter 가 있습니다. 이 리스너는 폭발하지 않은 Tomcat에 대한 전체 요청에 대해 총 1632ms 중 "제출 요청"(내가 첫 번째 웹 플로우 이벤트를 알고있는 한)을 1405ms보고하므로 약 200ms의 오버 헤드가 발생합니다.
그러나 폭발 된 Tomcat에서는 총 요청 지속 시간 7105ms 중에서 요청 된 JSF 단계가 5332ms (모든 JSF 단계가 5 초 내에 발생 함을 의미)로보고하므로 웹 플로우 요청 외부의 모든 항목에 대해 거의 2 초의 오버 헤드가 발생합니다 .
내 측정 필터 아래에 필터 체인에 org.ajax4jsf.webapp.BaseFilter 가 포함되어 org.ajax4jsf.webapp.BaseFilter Spring 서블릿이 호출됩니다.

2013-06-05 업데이트 : 지난 주에 진행된 모든 작업

작고 다소 늦은 업데이트 ... 애플리케이션 성능은 여전히 ​​약간의 시간이 지나면 빨려서 동작은 이상하게 유지됩니다. 프로파일 링은 아직 많은 도움이되지 못했지만 막대한 양의 데이터를 생성하여 해부하기가 어렵습니다. (성능 데이터를 살펴 보거나 프로덕션 시스템 프로필을 작성해보십시오 ... 한숨) 여러 테스트 (소프트웨어의 특정 부분 추출, 다른 응용 프로그램 배포 취소 등)를 수행했으며 실제로 전체 응용 프로그램에 영향을주는 몇 가지 개선 사항이있었습니다. EntityManager 의 기본 플러시 모드는 AUTO 이며 뷰 렌더링 중에 많은 플러시와 선택이 발생하며 항상 플러시가 필요한지 여부를 확인합니다.
그래서 우리는 RENDER_RESPONSE 동안 플러시 모드를 COMMIT 설정하는 JSF 위상 리스너를 구축했습니다. 이 전반적인 성능 이 많이 향상되었고 문제가 다소 완화 된 것으로 보입니다.

그러나 우리의 응용 프로그램 모니터링은 일부 tomcat 인스턴스의 일부 컨텍스트에서 완전히 미친 결과와 성능을 유지합니다. 잠시 후에 끝내야하는 작업 (실제로 전개 후 수행)처럼 이제는 4 초 이상 걸립니다. (이 번호는 브라우저의 수동 타이밍에 의해 지원되므로 문제를 일으키는 모니터링이 아닙니다.)

예를 들어 다음 그림을 참조하십시오.

이 다이어그램은 동일한 컨텍스트 (동일한 db, 동일한 구성, 동일한 jar를 의미)를 실행하는 두 개의 tomcat 인스턴스를 보여줍니다. 다시 파란색 선은 순수 DB 읽기 작업 (엔티티 목록 가져 오기, 반복 작업, 느린 수집 모음 및 관련 데이터 가져 오기)에 소요되는 시간입니다. turquoise-ish 및 red line은 여러 개의 뷰를 렌더링하고 Ajax 새로 고침을 각각 수행하여 측정됩니다. 청록색과 빨강의 두 요청에 의해 렌더링 된 데이터는 청색 선에 대해 쿼리 된 것과 거의 같습니다.

이제 인스턴스 1 (오른쪽)의 0700 주위에 순수 DB 시간의 엄청난 증가가 있습니다. 실제 렌더링 응답 시간에도 영향을 미치지 만, 단지 톰캣 1에만 영향을 미칩니다. Tomcat 0은 크게 영향을받지 않으므로 DB로 인해 발생할 수 없습니다 서버 또는 네트워크에 동일한 물리적 하드웨어에서 실행되는 두 개의 tomcats가 있습니다. Java 도메인의 소프트웨어 문제 여야합니다.

마지막 테스트에서 흥미로운 것을 발견했습니다. 모든 응답에는 "X-Powered-By : JSF / 1.2, JSF / 1.2"헤더가 포함되어 있습니다. 일부 (WebFlow가 생성 한 리디렉션 응답)도 "JSF / 1.2"를 세 번 포함합니다.
헤더를 설정하는 코드 부분을 추적하고이 헤더가이 스택에 의해 처음으로 설정되었습니다.

... at org.ajax4jsf.webapp.FilterServletResponseWrapper.addHeader(FilterServletResponseWrapper.java:384)
at com.sun.faces.context.ExternalContextImpl.<init>(ExternalContextImpl.java:131)
at com.sun.faces.context.FacesContextFactoryImpl.getFacesContext(FacesContextFactoryImpl.java:108)
at org.springframework.faces.webflow.FlowFacesContext.newInstance(FlowFacesContext.java:81)
at org.springframework.faces.webflow.FlowFacesContextLifecycleListener.requestSubmitted(FlowFacesContextLifecycleListener.java:37)
at org.springframework.webflow.engine.impl.FlowExecutionListeners.fireRequestSubmitted(FlowExecutionListeners.java:89)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:255)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:183)
at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.java:174)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
... several thousands ;) more

이 헤더가 두 번째로 설정됩니다.

at org.ajax4jsf.webapp.FilterServletResponseWrapper.addHeader(FilterServletResponseWrapper.java:384)   
at com.sun.faces.context.ExternalContextImpl.<init>(ExternalContextImpl.java:131)   
at com.sun.faces.context.FacesContextFactoryImpl.getFacesContext(FacesContextFactoryImpl.java:108)   
at org.springframework.faces.webflow.FacesContextHelper.getFacesContext(FacesContextHelper.java:46)   
at org.springframework.faces.richfaces.RichFacesAjaxHandler.isAjaxRequestInternal(RichFacesAjaxHandler.java:55)   
at org.springframework.js.ajax.AbstractAjaxHandler.isAjaxRequest(AbstractAjaxHandler.java:19)   
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.createServletExternalContext(FlowHandlerAdapter.java:216)   
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:182)   
at org.springframework.webflow.mvc.servlet.FlowController.handleRequest(FlowController.java:174)   
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)   
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)   
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)   
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)   
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)   
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)

이것이 문제를 나타낼 수 있는지는 잘 모르겠지만, 우리 서버에서 실행중인 다른 응용 프로그램에서는이 사실을 알지 못했기 때문에 약간의 힌트를 제공 할 수 있습니다. 그 프레임 워크 코드가 무엇을하고 있는지 전혀 모르겠다. (아직 나는 그것에 뛰어 들지 않았다.) 아마도 누군가 아이디어를 가지고있을 것인가? 아니면 막 다른 골목으로 뛰어 들까?

충수

내 CPU 벤치 마크 코드는 Math.tan을 계산하고 결과 값을 사용하여 서블릿 인스턴스의 일부 필드를 수정 (휘발성 / 동기화되지 않음)하는 루프로 구성되며 두 번째로 여러 정수 계산을 수행합니다. 이것은 정교하게 정교하지는 않지만 나는 잘 알지만 차트에 어떤 것을 보여주는 것처럼 보이지만 나는 그것이 무엇을 보여줄지 확신하지 못합니다. HotSpot이 내 모든 소중한 코드를 최적화하지 못하도록 필드 업데이트를 수행합니다.

    long time2 = System.nanoTime();
    for (int i = 0; i < 5000000; i++) {
        double tan = Math.tan(i);
        if (tan < 0) {
            this.l1++;
        } else {
            this.l2++;
        }
    }

    for (int i = 1; i < 7500; i++) {
        int n = i;
        while (n != 1) {
            this.steps++;
            if (n % 2 == 0) {
                n /= 2;
            } else {
                n = n * 3 + 1;
            }
        }
    }
    // This execution time is written to the client.
    time2 = System.nanoTime() - time2;

해결책

코드 캐시의 최대 크기 늘리기 :

-XX:ReservedCodeCacheSize=256m

배경

Tomcat 7 및 Java 1.7.0_15에서 실행되는 ColdFusion 10을 사용하고 있습니다. 우리의 증상은 당신과 비슷했습니다. 때때로 서버의 응답 시간과 CPU 사용량이 명백한 이유없이 많이 올라갈 수 있습니다. 마치 CPU가 느린 것처럼 보였습니다. 유일한 해결책은 ColdFusion (및 Tomcat)을 다시 시작하는 것이 었습니다.

초기 분석

메모리 사용량과 가비지 수집기 로그를 살펴 보았습니다. 우리 문제를 설명 할 수있는 것도 없었습니다.

내 다음 단계는 매시간 힙 덤프를 예약하고 VisualVM을 사용하여 정기적으로 샘플링을 수행하는 것이 었습니다. 목표는 비교할 수 있도록 감속 전후의 데이터를 얻는 것이 었습니다. 나는 그것을 성취 할 수 있었다.

샘플링에 한 가지 기능이있었습니다 : coldfusion.runtime.ConcurrentReferenceHashMap에서 get (). 아주 약간 전에 비교 된 감속 후에 많은 시간은 그것에서 보냈다. 함수가 어떻게 작동하는지 이해하는데 시간을 들였고 아마도 해시 함수에 문제가있어서 거대한 양동이가 생겼다는 이론을 개발했습니다. 힙 덤프를 사용하여 가장 큰 버킷에는 6 개의 요소 만 포함되어 있으므로 해당 이론을 무시했습니다.

코드 캐시

나는 "Java Performance : The Definitive Guide"를 읽을 때 마침내 바른 길을 걸었습니다. JIT 컴파일러에는 이전에 들어 보지 못한 코드 캐시에 대해 설명하는 장이 있습니다.

컴파일러 사용 안 함

수행 된 컴파일 수 (jstat로 모니터 됨)와 코드 캐시 (VisualVM의 메모리 풀 플러그인으로 모니터링 됨)의 크기를 모니터링 할 때 크기가 최대 크기 (이 환경에서 기본적으로 48MB - - 기본값은 Java 버전 및 Java 컴파일러에 따라 다릅니다. 코드 캐시가 가득 차면 JIT 컴파일러가 꺼졌습니다. "CodeCache가 꽉 찼습니다. 컴파일러가 비활성화되었습니다." 그 일이 생길 때 인쇄해야하지만 그 메시지를 보지 못했습니다. 사용중인 버전에 해당 메시지가 없을 수도 있습니다. 컴파일 횟수가 늘어나지 않아 컴파일러가 꺼져 있다는 것을 알고 있습니다.

최적화 해제가 계속됨

JIT 컴파일러는 이전에 컴파일 된 함수를 최적화 할 수 없으므로 함수가 인터프리터에 의해 다시 실행되도록 조정합니다 (함수가 향상된 컴파일로 대체되지 않는 한). 최적화되지 않은 함수는 가비지 수집되어 코드 캐시의 여유 공간을 확보 할 수 있습니다.

어떤 이유로 든 함수를 대체하기 위해 컴파일 된 것이 없더라도 함수는 계속 최적화되지 않았습니다. 코드 캐시에서 점점 더 많은 메모리를 사용할 수 있지만 JIT 컴파일러는 다시 시작되지 않습니다.

나는 절대로 -XX : + PrintCompilation을 사용할 수 없었지만, 감속을 경험했지만 ConcurrentReferenceHashMap.get () 또는이 함수가 종속되어있는 함수를 보았을 때 그 시점에 취소되지 않았을 것입니다.

결과

코드 캐시의 최대 크기를 256MB로 늘린 이후로는 속도 저하가 없었으며 일반적인 성능이 향상되었습니다. 현재 코드 캐시에는 110MB가 있습니다.


JVM GC 시간을 확인 했습니까? 일부 GC 알고리즘은 응용 프로그램 스레드를 '일시 중지'하고 응답 시간을 늘릴 수 있습니다.

jstat 유틸리티를 사용하여 가비지 수집 통계를 모니터 할 수 있습니다.

jstat -gcutil <pid of tomcat> 1000 100

위의 명령은 100 초 동안 매 1 초마다 GC 통계를 인쇄합니다. FGC / YGC 열을 살펴보십시오. 숫자가 계속 증가하면 GC 옵션에 문제가있는 것입니다.

응답 시간을 줄이려면 CMS GC로 전환 할 수 있습니다.

-XX:+UseConcMarkSweepGC

여기에서 더 많은 GC 옵션을 확인할 수 있습니다.


당신은 Quartz를 사용하고 있습니다. Quartz는 시간 제한적인 프로세스를 관리합니다. 이것은 특정 시간에 일어나는 것처럼 보입니다.

쿼츠 일정을 게시하고 이것이 맞는지 알려주십시오. 그렇다면, 내부 애플리케이션 프로세스가 리소스를 소비하기 시작할지 결정할 수 있습니다.

또는 응용 프로그램 코드의 일부가 마침내 활성화되어 메모리 캐시로 데이터를로드하기로 결정할 수도 있습니다. 최대 절전 모드를 사용하고 있습니다. 데이터베이스에 대한 호출을 확인하고 일치하는 항목이 있는지 확인하십시오.


앱이 한동안 느린 속도로 실행 된 후에 어떤 일이 발생합니까? 그렇다면 현재 진행중인 앱과 관련이없는 활동이 있는지 확인합니다. 바이러스 백신 검사 또는 시스템 / db 백업과 같은 것입니다.

그렇지 않다면 프로파일 러 (JProfiler, yourkit 등)를 사용하여 실행하는 것이 좋습니다.이 도구는 핫스팟을 쉽게 가리킬 수 있습니다.





tomcat7