Класс THPDFCoalescingRandomAccessSource
Оборачивает любой THPDFRandomAccessSource в ограниченный range-кэш с учитывающим отмену асинхронным prefetch
Объявление
constructor Create(
ASource: THPDFRandomAccessSource;
OwnsSource: Boolean = False;
BlockSize: Integer = 262144;
MaxCacheBytes: Int64 = 2097152;
MaxEntryBytes: Int64 = 0;
MaxCacheEntries: Integer = 0;
AdaptiveAdmission: Boolean = True);
procedure PrefetchRange(Offset, Count: Int64);
procedure ObserveReadPattern(Offset: Int64; Count: Integer);
function TransferAt(Offset, Count: Int64;
Destination: TStream): Int64;
procedure CancelPrefetch;
function IsPrefetchActive: Boolean;
procedure ClearCache;
procedure ConfigureCacheAdmission(MaxCacheBytes,
MaxEntryBytes: Int64; MaxCacheEntries: Integer;
AdaptiveAdmission: Boolean = True);
procedure GetStatistics(out Statistics: THPDFRangeCacheStatistics);
property BlockSize: Integer;
property MaxCacheBytes: Int64;
property MaxEntryBytes: Int64;
property MaxCacheEntries: Integer;
property AdaptiveAdmissionEnabled: Boolean;
property AsyncPrefetchEnabled: Boolean;
property AdaptiveReadAheadEnabled: Boolean;
property MaxReadAheadBlocks: Integer;
property SequentialReadToleranceBytes: Integer;
Объединение range-запросов
- При промахе кэша запрос расширяется до выровненного блока, покрывающего запрошенные байты, поэтому соседние чтения парсера делят один запрос к хранилищу
- Кэш соблюдает независимые лимиты на суммарные байты, на отдельную запись и опционально на количество записей, а слишком большой range обходит удержание в кэше
- Adaptive admission комбинирует порядок least recently used с ограниченным frequency sketch со старением, поэтому холодное сканирование читает напрямую, не вытесняя более горячие удержанные range-блоки
- Если разреженный источник не может отдать расширенный блок, обёртка возвращается к точному доступному запрошенному range
- Доступ к источнику сериализован, поэтому существующим подклассам не нужно становиться потокобезопасными
Асинхронный prefetch и отмена
PrefetchRange планирует один фоновый range и заменяет не связанный с ним предыдущий запрос
Основной промах кэша вне активного range отменяет worker до захвата блокировки источника, позволяя cooperative-транспорту быстро уступить видимой операции
Переопределите THPDFRandomAccessSource.ReadAtCancellable, чтобы проверять переданный THPDFCancellationToken во время сетевого или дискового I/O; унаследованная реализация проверяет отмену непосредственно до и после ReadAt
Выставьте AsyncPrefetchEnabled в False, если политика транспорта запрещает фоновый доступ
Адаптивный read-ahead
Поток парсера вызывает ObserveReadPattern после каждого успешного чтения; устойчивое чтение вперёд наращивает окно read-ahead через 1, 2, 4 и 8 блоков, а seek или чтение назад немедленно подавляет спекулятивный транспорт
SequentialReadToleranceBytes считает небольшие промежутки вперёд последовательным доступом, значение по умолчанию — 4096 байт; MaxReadAheadBlocks ограничивает адаптивное окно диапазоном от 1 до 32 блоков, по умолчанию — 8
На эффективное окно также действует лимит MaxCacheBytes, поэтому read-ahead не может намеренно превысить ёмкость кэша; после случайного прыжка уверенность в последовательном чтении восстанавливается постепенно
Выставьте AdaptiveReadAheadEnabled в False для фиксированного prefetch в один блок с сохранением асинхронного транспорта
Статистика
TransferAt берёт ссылки на удержанные блоки кэша и пишет их в приёмник, не выделяя и не заполняя промежуточный read buffer
THPDFRangeCacheStatistics сообщает количество и объём чтений из исходного хранилища, попадания и промахи кэша, добавления в кэш, отказы и вытеснения, frequency-добавления, отказы и старение, запросы prefetch, их завершения и отмены, последовательные и случайные чтения, подавленные prefetch-запросы, текущие и пиковые блоки read-ahead, прямые пересылки (вызовы и байты), а также текущее количество и объём кэшированных range-блоков
Владение
Когда OwnsSource равен True, уничтожение обёртки отменяет и дожидается worker, освобождает кэшированные range-блоки и уничтожает обёрнутый источник