 
 
 
 
 
 
   
 for the prefetch library
queue size. This is an empirical value which is about
 for the prefetch library
queue size. This is an empirical value which is about  of the total
number of pages accessed by all our testing cases, as will be shown in 
Table 1. We also set a threshold number
 of the total
number of pages accessed by all our testing cases, as will be shown in 
Table 1. We also set a threshold number  , 
and when there are at least this number of free entries available in the kernel 
prefetch queue, the prefetch thread will be woken up. These numbers may require 
tuning for different architectures. One could use the simple Backward 1 case, 
as will be described in the performance evaluation section, as a good guideline
on how to tune these numbers effectively.
, 
and when there are at least this number of free entries available in the kernel 
prefetch queue, the prefetch thread will be woken up. These numbers may require 
tuning for different architectures. One could use the simple Backward 1 case, 
as will be described in the performance evaluation section, as a good guideline
on how to tune these numbers effectively.
For prefetchable files, the AASFP kernel turns off 
Linux's sequential prefetching mechanism  
and supports application-specific prefetching. 
Whenever an AASFP application's computation thread makes a disk access call,
the kernel first satisfies this access with data already prefetched and stored
in the file buffer, then performs asynchronous disk read for a certain number of 
requests in the kernel-level prefetch queue.
That is, physical disk prefetching is triggered by disk accesses that
the computation thread makes.   
This scheme works well
for applications with periodic I/O calls. However, if an application
performs a long computation followed by a burst of I/O, physical disk prefetch operations  
may be invoked too late to mask all disk I/O delay.  
Therefore AASFP uses a timer-driven approach to schedule disk prefetch operations. 
That is, every time   
Linux's timer interrupt occurs (roughly every  ), the CPU  
scheduler will assign a higher priority to the prefetch thread
so that the prefetch thread can get scheduled sooner in the near future if  
it does not find any entry in the kernel-level
prefetch queue. Furthermore it will check whether there are prefetch 
entries in the kernel-level prefetch queue that should be moved to the disk queue
according to an algorithm described next. 
Before a request in the kernel-level prefetch queue is serviced, the 
kernel checks whether this request is still valid by comparing its
prefetch call ID with the number of disk I/O calls that the computation
thread has made up to that point.
If the prefetch entry's call ID 
is smaller, the entry is invalid 
and the kernel just deletes it. For a valid  
entry, the kernel dynamically determines whether to service that entry
at that moment. To make this decision, 
the kernel maintains the current number of entries in the disk queue (
), the CPU  
scheduler will assign a higher priority to the prefetch thread
so that the prefetch thread can get scheduled sooner in the near future if  
it does not find any entry in the kernel-level
prefetch queue. Furthermore it will check whether there are prefetch 
entries in the kernel-level prefetch queue that should be moved to the disk queue
according to an algorithm described next. 
Before a request in the kernel-level prefetch queue is serviced, the 
kernel checks whether this request is still valid by comparing its
prefetch call ID with the number of disk I/O calls that the computation
thread has made up to that point.
If the prefetch entry's call ID 
is smaller, the entry is invalid 
and the kernel just deletes it. For a valid  
entry, the kernel dynamically determines whether to service that entry
at that moment. To make this decision, 
the kernel maintains the current number of entries in the disk queue ( ),
the average time taken to service a disk request (
),
the average time taken to service a disk request ( ), and
the average computation time between two consecutive disk I/O calls for the 
application (
), and
the average computation time between two consecutive disk I/O calls for the 
application ( ). Suppose at time
). Suppose at time  , the current disk I/O call's ID is
, the current disk I/O call's ID is  ,
and the prefetch call ID for the entry is
,
and the prefetch call ID for the entry is  . Then, the
time available before the application accesses the 
block corresponding to the
. Then, the
time available before the application accesses the 
block corresponding to the  th prefetch call is approximately
th prefetch call is approximately 
 . 
A prefetch request that is sent to the disk queue at
. 
A prefetch request that is sent to the disk queue at  will
be expected to be completed at time
 will
be expected to be completed at time 
 . Therefore the kernel should service 
the prefetch request only if
. Therefore the kernel should service 
the prefetch request only if 
|  | 
|  | 
 and
 and 
 are empirical 
constants that need to be fine-tuned by the users based on hardware configurations
and workload characteristics based on system performance; this tuning
needs to be done only once per different architecture.
 are empirical 
constants that need to be fine-tuned by the users based on hardware configurations
and workload characteristics based on system performance; this tuning
needs to be done only once per different architecture.
 
 
 
 
