]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/Readahead.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "common/Readahead.h"
5 #include "common/Cond.h"
10 : m_trigger_requests(10),
11 m_readahead_min_bytes(0),
12 m_readahead_max_bytes(NO_LIMIT
),
15 m_consec_read_bytes(0),
18 m_readahead_trigger_pos(0),
23 Readahead::~Readahead() {
26 Readahead::extent_t
Readahead::update(const vector
<extent_t
>& extents
, uint64_t limit
) {
28 for (vector
<extent_t
>::const_iterator p
= extents
.begin(); p
!= extents
.end(); ++p
) {
29 _observe_read(p
->first
, p
->second
);
31 if (m_readahead_pos
>= limit
|| m_last_pos
>= limit
) {
33 return extent_t(0, 0);
35 std::pair
<uint64_t, uint64_t> extent
= _compute_readahead(limit
);
40 Readahead::extent_t
Readahead::update(uint64_t offset
, uint64_t length
, uint64_t limit
) {
42 _observe_read(offset
, length
);
43 if (m_readahead_pos
>= limit
|| m_last_pos
>= limit
) {
45 return extent_t(0, 0);
47 extent_t extent
= _compute_readahead(limit
);
52 void Readahead::_observe_read(uint64_t offset
, uint64_t length
) {
53 if (offset
== m_last_pos
) {
55 m_consec_read_bytes
+= length
;
58 m_consec_read_bytes
= 0;
59 m_readahead_trigger_pos
= 0;
63 m_last_pos
= offset
+ length
;
66 Readahead::extent_t
Readahead::_compute_readahead(uint64_t limit
) {
67 uint64_t readahead_offset
= 0;
68 uint64_t readahead_length
= 0;
69 if (m_nr_consec_read
>= m_trigger_requests
) {
70 // currently reading sequentially
71 if (m_last_pos
>= m_readahead_trigger_pos
) {
73 if (m_readahead_size
== 0) {
74 // initial readahead trigger
75 m_readahead_size
= m_consec_read_bytes
;
76 m_readahead_pos
= m_last_pos
;
78 // continuing readahead trigger
79 m_readahead_size
*= 2;
80 if (m_last_pos
> m_readahead_pos
) {
81 m_readahead_pos
= m_last_pos
;
84 m_readahead_size
= std::max(m_readahead_size
, m_readahead_min_bytes
);
85 m_readahead_size
= std::min(m_readahead_size
, m_readahead_max_bytes
);
86 readahead_offset
= m_readahead_pos
;
87 readahead_length
= m_readahead_size
;
89 // Snap to the first alignment possible
90 uint64_t readahead_end
= readahead_offset
+ readahead_length
;
91 for (vector
<uint64_t>::iterator p
= m_alignments
.begin(); p
!= m_alignments
.end(); ++p
) {
92 // Align the readahead, if possible.
93 uint64_t alignment
= *p
;
94 uint64_t align_prev
= readahead_end
/ alignment
* alignment
;
95 uint64_t align_next
= align_prev
+ alignment
;
96 uint64_t dist_prev
= readahead_end
- align_prev
;
97 uint64_t dist_next
= align_next
- readahead_end
;
98 if (dist_prev
< readahead_length
/ 2 && dist_prev
< dist_next
) {
99 // we can snap to the previous alignment point by a less than 50% reduction in size
100 ceph_assert(align_prev
> readahead_offset
);
101 readahead_length
= align_prev
- readahead_offset
;
103 } else if(dist_next
< readahead_length
/ 2) {
104 // we can snap to the next alignment point by a less than 50% increase in size
105 ceph_assert(align_next
> readahead_offset
);
106 readahead_length
= align_next
- readahead_offset
;
109 // Note that m_readahead_size should remain unadjusted.
112 if (m_readahead_pos
+ readahead_length
> limit
) {
113 readahead_length
= limit
- m_readahead_pos
;
116 m_readahead_trigger_pos
= m_readahead_pos
+ readahead_length
/ 2;
117 m_readahead_pos
+= readahead_length
;
120 return extent_t(readahead_offset
, readahead_length
);
123 void Readahead::inc_pending(int count
) {
124 ceph_assert(count
> 0);
125 m_pending_lock
.lock();
127 m_pending_lock
.unlock();
130 void Readahead::dec_pending(int count
) {
131 ceph_assert(count
> 0);
132 m_pending_lock
.lock();
133 ceph_assert(m_pending
>= count
);
135 if (m_pending
== 0) {
136 std::list
<Context
*> pending_waiting(std::move(m_pending_waiting
));
137 m_pending_lock
.unlock();
139 for (auto ctx
: pending_waiting
) {
143 m_pending_lock
.unlock();
147 void Readahead::wait_for_pending() {
149 wait_for_pending(&ctx
);
153 void Readahead::wait_for_pending(Context
*ctx
) {
154 m_pending_lock
.lock();
156 m_pending_lock
.unlock();
157 m_pending_waiting
.push_back(ctx
);
160 m_pending_lock
.unlock();
164 void Readahead::set_trigger_requests(int trigger_requests
) {
166 m_trigger_requests
= trigger_requests
;
170 uint64_t Readahead::get_min_readahead_size(void) {
171 std::lock_guard
lock(m_lock
);
172 return m_readahead_min_bytes
;
175 uint64_t Readahead::get_max_readahead_size(void) {
176 std::lock_guard
lock(m_lock
);
177 return m_readahead_max_bytes
;
180 void Readahead::set_min_readahead_size(uint64_t min_readahead_size
) {
182 m_readahead_min_bytes
= min_readahead_size
;
186 void Readahead::set_max_readahead_size(uint64_t max_readahead_size
) {
188 m_readahead_max_bytes
= max_readahead_size
;
192 void Readahead::set_alignments(const vector
<uint64_t> &alignments
) {
194 m_alignments
= alignments
;