티스토리 뷰
이전에 대량의 엑셀다운로드 처리 중 cpu가 급증하는 문제가 생겨 이를 해결한 내용을 다룬 적이 있는데요
그땐 시간이 없어서 그냥 XSSF에서 SXSSF로 바꾸면 되는구나~라고만 하고 넘어갔는데
SXSSF 컴포넌트는 어떻게 메모리를 관리하는건지 궁금해져서 공식문서를 다시 찬찬히 읽어봤습니다
이전 포스팅 👇
공식문서에서의 SXSSF에 대한 설명을 보면 슬라이딩 윈도우(sliding window)가 눈에 들어옵니다.
SXSSF achieves its low memory footprint by limiting access to the rows that are within a sliding window, while XSSF gives access to all rows in the document. Older rows that are no longer in the window become inaccessible, as they are written to the disk.
(https://poi.apache.org/components/spreadsheet/how-to.html#sxssf)
(무슨말인지 눈치껏 알겠는데 번역하려니까 어렵네요.......... 번역이 필요하신 분들은 구글번역기를 추천드립니다.. 🥲 )
슬라이딩 윈도우(Sliding Window) 알고리즘
슬라이딩 윈도우 알고리즘은 일정한 범위(=윈도우)를 유지하면서 이것을 이동시키면서 원하는 값을 추출하는 알고리즘입니다.
투포인터 알고리즘과 동일하게 시간복잡도 O(n^2)의 알고리즘을 O(n)으로 바꿔줍니다.
(by https://kimdia200.tistory.com/9)
SXSSF컴포넌트는 슬라이딩 윈도우를 어떻게 사용했을까?
기존의 XSSF 컴포넌트가 모든 row를 메모리에 할당한 후 write처리를 했다면, SXSSF컴포넌트는 슬라이딩 윈도우 알고리즘을 사용하여 윈도우의 크기를 초과하는 값이 나오면 첫번째 인덱스의 행부터 하나씩 힙 메모리에서 flush를 하고 write 하기 때문에 메모리를 효율적으로 사용할 수 있습니다
실제로 SXSSF의 write 메소드를 타고타고 들어가보면 아래 메소드가 나옵니다.
private void flushOneRow() throws IOException
{
Integer firstRowNum = _rows.firstKey();
if (firstRowNum!=null) {
int rowIndex = firstRowNum.intValue();
SXSSFRow row = _rows.get(firstRowNum);
_writer.writeRow(rowIndex, row);
_rows.remove(firstRowNum);
}
}
SXSSF컴포넌트는 인스턴스를 생성할 때 윈도우의 크기를 지정해줄 수 있습니다.
인자를 안넣으면 기본값 100이 들어갑니다.
아래는 공식문서의 예제코드입니다.
public static void main(String[] args) throws Throwable {
SXSSFWorkbook wb = new SXSSFWorkbook(100); // 100행까지만 메모리에 적재
Sheet sh = wb.createSheet();
for(int rownum = 0; rownum < 1000; rownum++){ // 1000행의 데이터 생성
Row row = sh.createRow(rownum);
for(int cellnum = 0; cellnum < 10; cellnum++){
Cell cell = row.createCell(cellnum);
String address = new CellReference(cell).formatAsString();
cell.setCellValue(address);
}
}
// 0~899번까지의 행은 메모리에서 flush되어 getRow() 시 null로 나옴
for(int rownum = 0; rownum < 900; rownum++){
Assert.assertNull(sh.getRow(rownum));
}
// 마지막 900~999번(100개)의 행만이 메모리에 남아있어 getRow()가 가능
for(int rownum = 900; rownum < 1000; rownum++){
Assert.assertNotNull(sh.getRow(rownum));
}
FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");
wb.write(out);
out.close();
}
알고리즘 스터디에서 공부했던 슬라이딩 윈도우의 실사용 예를 보게 되어 너무 반갑습니다
이를 통해 슬라이딩윈도우 뿐 아니라 힙 메모리에 대해서도 더 알게된 것 같습니다. ☺️
'JAVA' 카테고리의 다른 글
우선순위 큐(Priority Queue)와 힙(Heap) 자료구조 (0) | 2022.06.23 |
---|---|
스프링부트의 다중요청 처리 - Tomcat9 Thread Pool & JAVA NIO (0) | 2022.05.01 |
Java Bean과 Spring Bean (0) | 2022.04.16 |
테스트코드 관련 개념 정리 - xUnit, JUnit, Mockito, AssertJ, TDD 등 (1) | 2022.03.26 |
JUnit 기반의 MVC 테스트코드 작성해보기 - 컨트롤러 (1) | 2022.03.13 |
- Total
- Today
- Yesterday
- 라라벨
- laravel 테스트코드
- redis
- 샤딩
- 리눅스 컨테이너
- devops
- k8s
- docker
- 백엔드
- 쿠버네티스
- index
- springboot
- 샤드
- laravel 테스트
- phpUnit
- database
- mongoDB
- MySQL
- kubernetes
- php
- 분산처리
- 몽고디비
- 대규모 데이터 처리
- pods
- java
- laravel
- 도커
- mockery
- NoSQL
- 주니어개발자
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |