連続キャッシュの例

Contiguous Cache の例は、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

©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。