1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
9 #include "table/block_based/block_prefetcher.h"
11 #include "rocksdb/file_system.h"
12 #include "table/block_based/block_based_table_reader.h"
14 namespace ROCKSDB_NAMESPACE
{
15 void BlockPrefetcher::PrefetchIfNeeded(
16 const BlockBasedTable::Rep
* rep
, const BlockHandle
& handle
,
17 const size_t readahead_size
, bool is_for_compaction
,
18 const bool no_sequential_checking
,
19 const Env::IOPriority rate_limiter_priority
) {
20 // num_file_reads is used by FilePrefetchBuffer only when
21 // implicit_auto_readahead is set.
22 if (is_for_compaction
) {
23 rep
->CreateFilePrefetchBufferIfNotExists(
24 compaction_readahead_size_
, compaction_readahead_size_
,
25 &prefetch_buffer_
, /*implicit_auto_readahead=*/false,
26 /*num_file_reads=*/0, /*num_file_reads_for_auto_readahead=*/0);
30 // Explicit user requested readahead.
31 if (readahead_size
> 0) {
32 rep
->CreateFilePrefetchBufferIfNotExists(
33 readahead_size
, readahead_size
, &prefetch_buffer_
,
34 /*implicit_auto_readahead=*/false, /*num_file_reads=*/0,
35 /*num_file_reads_for_auto_readahead=*/0);
39 // Implicit readahead.
41 // If max_auto_readahead_size is set to be 0 by user, no data will be
43 size_t max_auto_readahead_size
= rep
->table_options
.max_auto_readahead_size
;
44 if (max_auto_readahead_size
== 0 || initial_auto_readahead_size_
== 0) {
48 if (initial_auto_readahead_size_
> max_auto_readahead_size
) {
49 initial_auto_readahead_size_
= max_auto_readahead_size
;
52 // In case of no_sequential_checking, it will skip the num_file_reads_ and
53 // will always creates the FilePrefetchBuffer.
54 if (no_sequential_checking
) {
55 rep
->CreateFilePrefetchBufferIfNotExists(
56 initial_auto_readahead_size_
, max_auto_readahead_size
,
57 &prefetch_buffer_
, /*implicit_auto_readahead=*/true,
59 rep
->table_options
.num_file_reads_for_auto_readahead
);
63 size_t len
= BlockBasedTable::BlockSizeWithTrailer(handle
);
64 size_t offset
= handle
.offset();
66 // If FS supports prefetching (readahead_limit_ will be non zero in that case)
67 // and current block exists in prefetch buffer then return.
68 if (offset
+ len
<= readahead_limit_
) {
69 UpdateReadPattern(offset
, len
);
73 if (!IsBlockSequential(offset
)) {
74 UpdateReadPattern(offset
, len
);
75 ResetValues(rep
->table_options
.initial_auto_readahead_size
);
78 UpdateReadPattern(offset
, len
);
80 // Implicit auto readahead, which will be enabled if the number of reads
81 // reached `table_options.num_file_reads_for_auto_readahead` (default: 2) and
82 // scans are sequential.
84 if (num_file_reads_
<= rep
->table_options
.num_file_reads_for_auto_readahead
) {
88 if (rep
->file
->use_direct_io()) {
89 rep
->CreateFilePrefetchBufferIfNotExists(
90 initial_auto_readahead_size_
, max_auto_readahead_size
,
91 &prefetch_buffer_
, /*implicit_auto_readahead=*/true, num_file_reads_
,
92 rep
->table_options
.num_file_reads_for_auto_readahead
);
96 if (readahead_size_
> max_auto_readahead_size
) {
97 readahead_size_
= max_auto_readahead_size
;
100 // If prefetch is not supported, fall back to use internal prefetch buffer.
101 // Discarding other return status of Prefetch calls intentionally, as
102 // we can fallback to reading from disk if Prefetch fails.
103 Status s
= rep
->file
->Prefetch(
105 BlockBasedTable::BlockSizeWithTrailer(handle
) + readahead_size_
,
106 rate_limiter_priority
);
107 if (s
.IsNotSupported()) {
108 rep
->CreateFilePrefetchBufferIfNotExists(
109 initial_auto_readahead_size_
, max_auto_readahead_size
,
110 &prefetch_buffer_
, /*implicit_auto_readahead=*/true, num_file_reads_
,
111 rep
->table_options
.num_file_reads_for_auto_readahead
);
115 readahead_limit_
= offset
+ len
+ readahead_size_
;
116 // Keep exponentially increasing readahead size until
117 // max_auto_readahead_size.
118 readahead_size_
= std::min(max_auto_readahead_size
, readahead_size_
* 2);
120 } // namespace ROCKSDB_NAMESPACE