개인용 클라우드 서비스를 재정비하고 있는데 기존에는 파일갯수가 기껏해야 몇천개 수준에서 갑자기 몇백만개 수준으로 파일이 급증하면서 너무 느려져서 업그레이드 해야할 필요성을 느꼈습니다.
그럼 기존과 변경한 방식을 예시코드를 통해 비교해보겠습니다.
기존
DFS 방식
- 해당 폴더에 가서 파일 리스트 확인 후 정렬
- 파일 리스트에 폴더가 존재시 해당 폴더를 탐색
코드
public void filesDFS(){
String originPath = "E:\\WorkSpace";
File defaultFile = new File(originPath);
File[] files = defaultFile.listFiles();
long size = files.length;
for(File file : files){
size += DFS(file.getPath(), 0);
}
System.out.println("filesDFS total size : "+size);
}
private int DFS(String path, int size){
File defaultFile = new File(path);
File[] files = defaultFile.listFiles();
for(File file : files){
size++;
if(file.isDirectory()){
size = DFS(file.getPath(), size);
}
}
return size;
}
변경한 방식
Files.walk()를 사용
- 한번에 하위 폴더 내용들까지 싹 다 탐색
코드
public void filesWalk(){
String originPath = "E:\\WorkSpace";
Path dirPath = Paths.get(originPath);
List<Path> listPath;
try {
Stream<Path> walk = Files.walk(dirPath);
listPath = walk.collect(Collectors.toList());
System.out.println("walk end. path size : "+listPath.size());
for(Path path: listPath){
File file = new File(path.toString()); // File 타입으로 받아와야 원하는 파일 데이터를 얻을 수 있으므로 Path->File은 필수조건이기에 넣어봤습니다.
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
실행 결과
검색된 파일 및 폴더 수 : 3209618개
Files.work()를 이용한 탐색 시간 : 65초
DFS를 이용한 탐색시간 : 318초
결과에 따른 개인적인 견해
이러한 결과가 나온 이유가 여러 있겠지만
기존 방식과 Files.walk()의 작동방식의 차이가 요인이지 않을까 합니다.
그러면 어떤 방식이 이렇게 차이를 냈을지 여러 생각을 해봤습니다.
1. 수많은 재귀호출은 효율성이 좋지못하다.
기존에는 재귀호출방식으로 탐색해야할 폴더의 수가 많으면 많아질수록 더 많은 자원을 요구할 수 밖에 없습니다.
그러면 재귀호출을 안하고 BFS 방식으로 하면 적어져야 합니다.
아래는 BFS 방식 코드입니다.
public void BFS(){
String originPath = "E:\\WorkSpace";
Queue<File> queue = new LinkedList<>();
File originFile = new File(originPath);
File[] files = originFile.listFiles();
for(File file : files){
if(file.isDirectory()) queue.add(file);
}
while(!queue.isEmpty()){
int qSize = queue.size();
for(int i=0;i<qSize;i++){
File file = queue.poll();
File[] fileArr = file.listFiles();
for(File tmpFile : fileArr){
if(tmpFile.isDirectory()) queue.add(tmpFile);
}
}
}
}
결과
아이러니하게 오히려 BFS가 가장 시간이 오래 걸렸습니다.
그러면 잦은 재귀호출이 실행결과를 오래 걸리게 하는 이유에서는 멀어집니다.
다음으로 예상이 가는건 I/O 호출 빈도입니다. 이 부분은 다음 기회에 한번 따로 작성해보도록 하겠습니다.
※ 기타
Files.walk() 코드를 찾아보니 파일트리를 통해 데이터를 추출하고 이를 Stream으로 변환하여 데이터를 반환하는 방식이였습니다. 아래 공식 페이지에 walk부분을 찾아보시면 파일 트리 구조로 작동한다고 합니다.
언제나 의견은 환영입니다.
'개발잡담 > 기타' 카테고리의 다른 글
Git 명령어 사용법 - 기본 2 (0) | 2024.01.17 |
---|---|
Git 명령어 사용법 - 기본 1 (0) | 2024.01.15 |
Git commit 메세지 템플릿 설정 (0) | 2023.11.07 |
Yolo v5를 이용한 간단하게 AI 이미지 인식 (0) | 2023.05.05 |
rand보단 well512 (0) | 2016.07.25 |