NeuroWhAI의 잡블로그

[Rust] 오늘의 리팩토링 - HashMap 관련 본문

개발 및 공부/설계

[Rust] 오늘의 리팩토링 - HashMap 관련

NeuroWhAI 2019. 1. 13. 14:14


if self.cache.contains_key(ids) {
    let sub_cache = self.cache.get_mut(ids).unwrap();
    if sub_cache.contains_key(page_id) {
        let data = sub_cache.get_mut(page_id).unwrap();
        data.update(cnt);
    }
    else {
        // 캐시가 비정상적으로 커질 가능성 배제.
        if sub_cache.len() >= self.max_sub_cache_len {
            sub_cache.clear();
        }

        sub_cache.insert(page_id.clone(), CacheData::new(cnt));
    }
}
else {
    let mut sub_cache = HashMap::new();
    sub_cache.insert(page_id.clone(), CacheData::new(cnt));

    // 캐시가 비정상적으로 커질 가능성 배제.
    if self.cache.len() >= self.max_cache_len {
        self.cache.clear();
    }

    self.cache.insert(ids.clone(), sub_cache);
}

티스토리 글 조회수 표시용으로 예전에 만들었던 서버의 코드 중 일부입니다.

당시엔 Rust의 HashMap 인터페이스를 잘 몰라서 기본적인 메소드만 사용한거라 코드가 더럽습니다.

요것을 아래 코드로 바꾸었습니다.

// 캐시가 비정상적으로 커질 가능성 배제.
if self.cache.len() >= self.max_cache_len {
    self.cache.clear();
}

let max_sub_cache_len = self.max_sub_cache_len;
self.cache.entry(ids.clone())
    .and_modify(|sub_cache| {
        // 캐시가 비정상적으로 커질 가능성 배제.
        if sub_cache.len() >= max_sub_cache_len {
            sub_cache.clear();
        }
    })
    .or_insert(HashMap::new())
    // sub_cache
    .entry(page_id.clone())
    .and_modify(|data| data.update(cnt))
    .or_insert(CacheData::new(cnt));

코드 줄 수도 줄었고 Entry를 사용해서 HashMap에서 요소를 탐색하고 삽입할 때 중복되는 연산도 (아마) 제거하였습니다.

다만 좀 걸리는게 max_sub_cache_len인데

이걸 그냥 바로 쓰니까 Rust의 borrow 관련 규칙에 걸려서 저렇게 했어야 했습니다 ㅠ

그리고 원래 리팩토링은 로직이 달라지지 않아야 좋은데 이건 달라진 부분이 하나 있습니다.

cache의 크기(len) 검사를 insert가 있을 예정일때만 수행하던 것을 항상 수행하도록 바꿔서

크기가 max를 넘지 않았고 넘지 않을 것임에도 캐시가 초기화 될 수 있습니다.

뭐 사실 그렇게 중요한 사항이 아니니까 그냥 이대로 쓰려고 합니다.


코드 리뷰(?) 환영합니다.


끝까지 보신 분들을 위해 좋은 Rust 치트 시트 공유합니다.

https://www.breakdown-notes.com/make/load/rust_cs_canvas/true



Comments