Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
3ae5133b
Commit
3ae5133b
authored
Apr 08, 2012
by
Robert Haas
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Teach SLRU code to avoid replacing I/O-busy pages.
Patch by me; review by Tom Lane and others.
parent
d5375491
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
57 additions
and
35 deletions
+57
-35
src/backend/access/transam/slru.c
src/backend/access/transam/slru.c
+57
-35
No files found.
src/backend/access/transam/slru.c
View file @
3ae5133b
...
...
@@ -403,12 +403,6 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok,
/* Acquire per-buffer lock (cannot deadlock, see notes at top) */
LWLockAcquire
(
shared
->
buffer_locks
[
slotno
],
LW_EXCLUSIVE
);
/*
* Temporarily mark page as recently-used to discourage
* SlruSelectLRUPage from selecting it again for someone else.
*/
SlruRecentlyUsed
(
shared
,
slotno
);
/* Release control lock while doing I/O */
LWLockRelease
(
shared
->
ControlLock
);
...
...
@@ -909,9 +903,12 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
{
int
slotno
;
int
cur_count
;
int
bestslot
;
int
best_delta
;
int
best_page_number
;
int
bestvalidslot
=
0
;
/* keep compiler quiet */
int
best_valid_delta
=
-
1
;
int
best_valid_page_number
=
0
;
/* keep compiler quiet */
int
bestinvalidslot
=
0
;
/* keep compiler quiet */
int
best_invalid_delta
=
-
1
;
int
best_invalid_page_number
=
0
;
/* keep compiler quiet */
/* See if page already has a buffer assigned */
for
(
slotno
=
0
;
slotno
<
shared
->
num_slots
;
slotno
++
)
...
...
@@ -922,8 +919,16 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
}
/*
* If we find any EMPTY slot, just select that one. Else locate the
* least-recently-used slot to replace.
* If we find any EMPTY slot, just select that one. Else choose a
* victim page to replace. We normally take the least recently used
* valid page, but we will never take the slot containing
* latest_page_number, even if it appears least recently used. We
* will select a slot that is already I/O busy only if there is no
* other choice: a read-busy slot will not be least recently used once
* the read finishes, and waiting for an I/O on a write-busy slot is
* inferior to just picking some other slot. Testing shows the slot
* we pick instead will often be clean, allowing us to begin a read
* at once.
*
* Normally the page_lru_count values will all be different and so
* there will be a well-defined LRU page. But since we allow
...
...
@@ -932,9 +937,6 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
* acquire the same lru_count values. In that case we break ties by
* choosing the furthest-back page.
*
* In no case will we select the slot containing latest_page_number
* for replacement, even if it appears least recently used.
*
* Notice that this next line forcibly advances cur_lru_count to a
* value that is certainly beyond any value that will be in the
* page_lru_count array after the loop finishes. This ensures that
...
...
@@ -944,9 +946,6 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
* multiple pages with the same lru_count.
*/
cur_count
=
(
shared
->
cur_lru_count
)
++
;
best_delta
=
-
1
;
bestslot
=
0
;
/* no-op, just keeps compiler quiet */
best_page_number
=
0
;
/* ditto */
for
(
slotno
=
0
;
slotno
<
shared
->
num_slots
;
slotno
++
)
{
int
this_delta
;
...
...
@@ -968,34 +967,57 @@ SlruSelectLRUPage(SlruCtl ctl, int pageno)
this_delta
=
0
;
}
this_page_number
=
shared
->
page_number
[
slotno
];
if
((
this_delta
>
best_delta
||
(
this_delta
==
best_delta
&&
ctl
->
PagePrecedes
(
this_page_number
,
best_page_number
)))
&&
this_page_number
!=
shared
->
latest_page_number
)
if
(
this_page_number
==
shared
->
latest_page_number
)
continue
;
if
(
shared
->
page_status
[
slotno
]
==
SLRU_PAGE_VALID
)
{
if
(
this_delta
>
best_valid_delta
||
(
this_delta
==
best_valid_delta
&&
ctl
->
PagePrecedes
(
this_page_number
,
best_valid_page_number
)))
{
bestvalidslot
=
slotno
;
best_valid_delta
=
this_delta
;
best_valid_page_number
=
this_page_number
;
}
}
else
{
bestslot
=
slotno
;
best_delta
=
this_delta
;
best_page_number
=
this_page_number
;
if
(
this_delta
>
best_invalid_delta
||
(
this_delta
==
best_invalid_delta
&&
ctl
->
PagePrecedes
(
this_page_number
,
best_invalid_page_number
)))
{
bestinvalidslot
=
slotno
;
best_invalid_delta
=
this_delta
;
best_invalid_page_number
=
this_page_number
;
}
}
}
/*
* If all pages (except possibly the latest one) are I/O busy, we'll
* have to wait for an I/O to complete and then retry. In that unhappy
* case, we choose to wait for the I/O on the least recently used slot,
* on the assumption that it was likely initiated first of all the I/Os
* in progress and may therefore finish first.
*/
if
(
best_valid_delta
<
0
)
{
SimpleLruWaitIO
(
ctl
,
bestinvalidslot
);
continue
;
}
/*
* If the selected page is clean, we're set.
*/
if
(
shared
->
page_status
[
bestslot
]
==
SLRU_PAGE_VALID
&&
!
shared
->
page_dirty
[
bestslot
])
return
bestslot
;
if
(
!
shared
->
page_dirty
[
bestvalidslot
])
return
bestvalidslot
;
/*
* We need to wait for I/O. Normal case is that it's dirty and we
* must initiate a write, but it's possible that the page is already
* write-busy, or in the worst case still read-busy. In those cases
* we wait for the existing I/O to complete.
* Write the page.
*/
if
(
shared
->
page_status
[
bestslot
]
==
SLRU_PAGE_VALID
)
SlruInternalWritePage
(
ctl
,
bestslot
,
NULL
);
else
SimpleLruWaitIO
(
ctl
,
bestslot
);
SlruInternalWritePage
(
ctl
,
bestvalidslot
,
NULL
);
/*
* Now loop back and try again. This is the easiest way of dealing
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment