연속 캐시 예시

'연속 캐시' 예제는 ' QContiguousCache '를 사용하여 매우 큰 모델의 메모리 사용량을 관리하는 방법을 보여줍니다. 일부 환경에서는 메모리가 제한되어 있으며, 메모리가 충분하더라도 사용자는 애플리케이션이 과도한 메모리를 사용하는 것을 꺼립니다. 전체 목록을 메모리에 로드하는 대신 QContiguousCache 를 사용하여 목록을 관리하면, 애플리케이션이 액세스하는 데이터 세트의 크기와 관계없이 메모리 사용량을 제한할 수 있습니다.

QContiguousCache 를 사용하는 가장 간단한 방법은 항목이 요청될 때마다 캐싱하는 것입니다. 뷰가 N번째 행의 항목을 요청할 때, N과 가까운 행에 있는 항목들도 함께 요청할 가능성이 높기 때문입니다.

QVariant RandomListModel::data(const QModelIndex&index, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    int row = index.row();

    if (row > m_rows.lastIndex()) {
        if (row - m_rows.lastIndex() > lookAhead)
            cacheRows(row - halfLookAhead, qMin(m_count, row + halfLookAhead));
        else while (row > m_rows.lastIndex())
                m_rows.append(fetchRow(m_rows.lastIndex() + 1));
    } else if (row < m_rows.firstIndex()) {
        if (m_rows.firstIndex() - row > lookAhead)
            cacheRows(qMax(0, row - halfLookAhead), row + halfLookAhead);
       else while (row < m_rows.firstIndex())
                m_rows.prepend(fetchRow(m_rows.firstIndex() - 1));
    }

    return m_rows.at(row);
}

void RandomListModel::cacheRows(int from, int to) const
{
    for (int i = from; i <= to;++i)
        m_rows.insert(i, fetchRow(i));
}

행 데이터를 가져온 후, 이 클래스는 해당 행이 연속 캐시의 현재 범위 내에 있는지 확인합니다. 대신 다음과 같은 코드를 사용하는 것도 마찬가지로 유효했을 것입니다.

while (row > m_rows.lastIndex())
    m_rows.append(fetchWord(m_rows.lastIndex()+1);
while (row < m_rows.firstIndex())
    m_rows.prepend(fetchWord(m_rows.firstIndex()-1);

그러나 스크롤바를 직접 사용할 경우 목록이 행을 건너뛰는 경우가 많아, 위의 코드를 사용하면 이전 행과 다음 행 사이의 모든 행이 불러오게 됩니다.

QContiguousCache::lastIndex() 및 QContiguousCache::firstIndex()를 사용하면 이 예제에서 캐시가 현재 목록의 어느 부분을 캐싱하고 있는지 확인할 수 있습니다. 이 값들은 캐시 자체 메모리 내의 인덱스를 나타내는 것이 아니라, 캐시가 나타내는 가상 무한 배열을 나타냅니다.

QContiguousCache::append() 및 QContiguousCache::prepend()를 사용함으로써, 요청된 행이 현재 캐시 범위에서 멀리 이동하지 않은 경우 화면에 여전히 표시될 수 있는 항목이 손실되지 않도록 보장합니다. QContiguousCache::insert()는 QContiguousCache 가 간격을 허용하지 않기 때문에 잠재적으로 캐시에서 하나 이상의 항목을 제거할 수 있습니다. 캐시가 서로 상당한 간격이 있는 행들 사이를 빠르게 오가야 하는 경우, 대신 QCache 를 사용하는 것을 고려해 보십시오.

이것으로 끝입니다. 매우 큰 목록에 대해 최소한의 메모리만 사용하는, 지극히 합리적인 캐시입니다. 이 경우, 단어를 캐시에 넣는 액세서는 고정된 정보가 아닌 무작위 정보를 생성합니다. 이를 통해 예제를 실행할 때 캐시 범위가 특정 행 수에 대해 어떻게 유지되는지 확인할 수 있습니다.

QString RandomListModel::fetchRow(int position) const
{
    return QString::number(QRandomGenerator::global()->bounded(++position));
}

또한 애플리케이션의 페인트 루틴 외부에서 항목을 캐시로 미리 가져오는 것도 고려해 볼 만합니다. 이는 별도의 스레드를 사용하거나, 현재 캐시 범위 밖의 행이 요청되기 전에 캐시 범위를 점진적으로 확장하는 QTimer 를 사용하여 수행할 수 있습니다.

예제 프로젝트 @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.