티스토리 뷰

728x90

이전에 대량의 엑셀다운로드 처리 중 cpu가 급증하는 문제가 생겨 이를 해결한 내용을 다룬 적이 있는데요

그땐 시간이 없어서 그냥 XSSF에서 SXSSF로 바꾸면 되는구나~라고만 하고 넘어갔는데

SXSSF 컴포넌트는 어떻게 메모리를 관리하는건지 궁금해져서 공식문서를 다시 찬찬히 읽어봤습니다

 

이전 포스팅 👇

 

[Apache POI] 다량의 데이터 엑셀 다운로드 처리로 인한 서버 장애 대응 후기

스테이징 QA 도중 갑자기 사이트의 모든 기능이 먹통이 됐다는 소식을 들었습니다. 확인해보니 CPU 사용량이 급증하여 서버가 다운됐던 것이었습니다. 우선 서버를 재부팅하여 먹통 문제는 해결

jibsakim.tistory.com

 

공식문서에서의 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();
   }

알고리즘 스터디에서 공부했던 슬라이딩 윈도우의 실사용 예를 보게 되어 너무 반갑습니다

이를 통해 슬라이딩윈도우 뿐 아니라 힙 메모리에 대해서도 더 알게된 것 같습니다. ☺️

728x90
댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함