Archive v0.1.0 — 사진/영상 라이브러리 관리 프로그램
Tauri v2 + SolidJS + SQLite + ffmpeg 사이드카로 구현한 크로스플랫폼 사진·영상 관리 앱. 로컬/NAS(SFTP·WebDAV·FTP) 소스, 가상 그리드, 인앱 재생, 태그/이동/삭제/undo, 중복 탐지, 포터블 배포. - archive-db: SQLite 스키마·마이그레이션·단일 writer 스레드 + FTS5 trigram - archive-vfs: VFS 4백엔드(local/sftp/ftp/webdav) + 자격증명(키체인/볼트) - archive-indexer: 스캔·해시·썸네일·중복탐지·태그·파일작업·유지보수 - archive-media: localhost HTTP 미디어 서버(Range) + ffmpeg 스트림 잡 - 프론트: 3-pane UI, justified 가상 그리드, 라이트박스, 중복 검토 패널 Rust 테스트 49개 통과. CI: win x64/arm64 포터블 zip + macOS universal dmg. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
//! 성능 측정 (기본 무시). 실행:
|
||||
//! ARCHIVE_PERF_DIR=<50k폴더> cargo test -p archive-indexer --release --test perf_scan -- --ignored --nocapture
|
||||
|
||||
use archive_db::Db;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn scan_perf() {
|
||||
let Ok(dir) = std::env::var("ARCHIVE_PERF_DIR") else {
|
||||
eprintln!("ARCHIVE_PERF_DIR 미설정 — 건너뜀");
|
||||
return;
|
||||
};
|
||||
let dbdir = tempfile::tempdir().unwrap();
|
||||
let db = Arc::new(Db::open(&dbdir.path().join("perf.db")).unwrap());
|
||||
let root = std::path::Path::new(&dir);
|
||||
let cancel = AtomicBool::new(false);
|
||||
|
||||
let dir_owned = dir.clone();
|
||||
db.with_write(move |c| {
|
||||
c.execute("INSERT INTO sources(id,kind,name,root) VALUES(1,'local','perf',?1)", [&dir_owned])?;
|
||||
Ok(())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// 1차 스캔 (전체)
|
||||
let t0 = Instant::now();
|
||||
let stats = archive_indexer::pipeline::scan_source(&db, 1, root, &cancel, |_| {}).unwrap();
|
||||
let scan1 = t0.elapsed();
|
||||
|
||||
// 메타데이터
|
||||
let t1 = Instant::now();
|
||||
let meta = archive_indexer::meta::extract_image_meta(&db, 1, &cancel).unwrap();
|
||||
let meta_dur = t1.elapsed();
|
||||
|
||||
// 2차 스캔 (무변경 — 스냅샷 비교)
|
||||
let t2 = Instant::now();
|
||||
let stats2 = archive_indexer::pipeline::scan_source(&db, 1, root, &cancel, |_| {}).unwrap();
|
||||
let scan2 = t2.elapsed();
|
||||
|
||||
eprintln!("=== 성능 (릴리스) ===");
|
||||
eprintln!("파일 수: {}", stats.seen);
|
||||
eprintln!("1차 스캔: {:.2}s ({} added)", scan1.as_secs_f64(), stats.added);
|
||||
eprintln!("메타 추출: {:.2}s ({} 이미지)", meta_dur.as_secs_f64(), meta);
|
||||
eprintln!("무변경 재스캔: {:.2}s (added={}, changed={})", scan2.as_secs_f64(), stats2.added, stats2.changed);
|
||||
|
||||
assert_eq!(stats2.added, 0);
|
||||
assert_eq!(stats2.changed, 0);
|
||||
}
|
||||
Reference in New Issue
Block a user