자바 성능 튜닝 이야기 책의 9, 10 장 내용으로, IO와 로깅을 할 때, 성능을 위해서 고려할 사항들에 대한 간단 정리이다.
IO는 잘못하면 큰 성능 저하를 일으킬 수 있는 비용이 큰 동작이다. 만약 IO가 있는 비즈니스 로직에서 성능 저하가 있다면 아래 항목을 확인해보자.
IO를 자주하지 않고 모아서 작업할 수록 성능의 이점이 있다.
매 request마다 IO를 하고 있는지 확인이 필요하다. 만약 request마다 IO가 동작하고 있다면, request가 몰렸을 때 IO부하가 증가하여 해당 부분이 병목이 될 수 있다. 데몬 스레드로 미리 IO작업을 주기적으로 하고 request때는 메모리에 있는 정보를 조회하기만 하도록 하는 것이다.
DirectByteBuffer
를 잘못 사용하고 있는지 확인하자NIO 라이브러리를 사용할 때 ByteBuffer
를 사용하는 경우가 있다. 이때 allocateDirect()
메서드를 사용하게되면 BirectByteBuffer
객체를 생성하게 된다. 그런데 이 DirectByteBuffer
객체는 필요할 때 계속 생성해서는 안되는 객체이다.
DirectByteBuffer
생성자는 Bits
라는 클래스의 reserveMemory()
메서드를 호출한다. 이 reserveMemory()
메서드는 JVM에 할당되어 있는 메모리보다 더 많은 메모리를 요구할 경우 System.gc()
메서드를 호출하도록 되어있다. 따라서 무차별적으로 System.gc()
메서드를 부르는 상황이 유발될 수 있게되는 것이다.
lastModified()
대신 WatcherService
를 고려해보자lastModified()
를 통하여 변경사항이 없음에도 불구하고 계속 불필요한 확인 작업을 지속적으로 하지말고, WatcherService
를 통하여 event 방식으로 수정에 대한 정보를 가져오도록 하자.
로깅은 디버깅을 위해서 언제나 필요하지만 실제 운영 환경에는 최대한 영향을 미치지 않도록 정말 필요하다 생각하는 곳에 넣어야 한다. 잘못하면 성능에 영향을 생각보다 많이 미치게 된다. 따라서 로깅이 큰 의미없이 삽입되어 있지 않은지 언제나 고민이 필요하다.
System.out.println()
은 없애자무조건 지워도 된다고 생각한다.
log 파일을 만든다면, 로깅도 아주 자주 일어나는 IO 작업이다. 이 작업을 매 로깅 메서드 호출바다 동기적으로 하게 되면 당연히 성능 저하가 있을 수 있다. 이 작업을 비동기적으로 변경하면 response 시간을 단축할 수 있다.
isLoggable()
메서드로 처리하자로깅 메서드 호출 전에, if(logger.isLoggable(Level.INFO))
와 같은 조건문을 로그 처리 전에 삽입을 하면, 로깅을 위한 생성자 생성이나 로직들이 의미없이 동작하는 것을 방지할 수 있다.
코딩은 습관이다. 나쁜 습관은 고쳐야 발전한다.
자바 성능 튜닝 이야기 9, 10