XrdClientReadAhead.cc

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////
00002 //                                                                      //
00003 // XrdClientReadAhead                                                   //
00004 //                                                                      //
00005 // Author: Fabrizio Furano (CERN IT-DM, 2009)                           //
00006 //                                                                      //
00007 // Classes to implement a selectable read ahead decision maker          //
00008 //                                                                      //
00009 //////////////////////////////////////////////////////////////////////////
00010 
00011 //         $Id: XrdClientReadAhead.cc 30949 2009-11-02 16:37:58Z ganis $
00012 
00013 const char *XrdClientReadAheadCVSID = "$Id: XrdClientReadAhead.cc 30949 2009-11-02 16:37:58Z ganis $";
00014 
00015 #include "XrdClientReadAhead.hh"
00016 #include "XrdClientConst.hh"
00017 #include "XrdClientVector.hh"
00018 
00019 
00020 
00021 bool XrdClientReadAheadMgr::TrimReadRequest(long long &offs, long &len, long rasize, long blksz) {
00022 
00023     if (!blksz) return true;
00024 
00025     long long newoffs;
00026     long newlen;
00027 
00028     long long lastbyte;
00029 
00030     newoffs = (long long)(offs / blksz);
00031     newoffs *= blksz;
00032 
00033     lastbyte = offs+len+blksz-1;
00034     lastbyte = (long long)(lastbyte / blksz);
00035     lastbyte *= blksz;
00036     
00037     newlen = lastbyte-newoffs;
00038 
00039 //    std::cerr << "Trim: " << offs << "," << len << " --> " << newoffs << "," << newlen << std::endl;
00040     offs = newoffs;
00041     len = newlen;
00042     return true;
00043 
00044 }
00045 
00046 
00047 
00048 
00049 
00050 // -----------------------------------------------------------------------
00051 
00052 
00053 
00054 
00055 
00056 
00057 // A basic implementation. Purely sequential read ahead
00058 class XrdClientReadAhead_pureseq : public XrdClientReadAheadMgr {
00059 
00060 protected:
00061    long long RALast;
00062 
00063 public:
00064 
00065    XrdClientReadAhead_pureseq() {
00066       RALast = 0;
00067    }
00068 
00069    virtual int GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz);
00070 
00071    virtual int Reset() {
00072       RALast = 0;
00073       return 0;
00074    }
00075 
00076 };
00077 
00078 
00079 
00080 
00081 
00082 int XrdClientReadAhead_pureseq::GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz) {
00083 
00084    if (!blksz) blksz = 128*1024;
00085 
00086    // We read ahead only if (offs+len) lies in an interval of RALast not bigger than the readahead size
00087    if ( (RALast - (offset+len) < RASize) &&
00088         (RALast - (offset+len) > -RASize) &&
00089         (RASize > 0) ) {
00090       
00091       // This is a HIT case. Async readahead will try to put some data
00092       // in advance into the cache. The higher the araoffset will be,
00093       // the best chances we have not to cause overhead
00094       raoffset = xrdmax(RALast, offset + len);
00095       ralen = xrdmin(RASize,
00096                      offset + len + RASize - raoffset);
00097       
00098       if (ralen > 0) {
00099          TrimReadRequest(raoffset, ralen, RASize, blksz);
00100          RALast = raoffset + ralen;
00101          return 0;
00102       }
00103    }
00104    
00105    return 1;
00106    
00107 };
00108 
00109 
00110 // -----------------------------------------------------------------------
00111 
00112 
00113 
00114 
00115 
00116 
00117 // Another read ahead schema. A window centered on the recent average slides through the file
00118 //  following the stream of the requests
00119 class XrdClientReadAhead_slidingavg : public XrdClientReadAheadMgr {
00120 
00121 protected:
00122    long long RALast;
00123 
00124    long long LastOffsSum, LastOffsSum2;
00125    long long LastOffsSumsq, LastOffsSumsq2;
00126    XrdClientVector<long long> LastOffs;
00127    XrdClientVector<long long> LastAvgApprox, LastAvgApprox2;
00128 public:
00129 
00130    XrdClientReadAhead_slidingavg() {
00131       RALast = 0;
00132       LastOffsSum = LastOffsSum2 = 0;
00133       LastOffsSumsq = LastOffsSumsq2 = 0;
00134 
00135 
00136    }
00137 
00138    virtual int GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz);
00139 
00140    virtual int Reset() {
00141       RALast = 0;
00142       LastOffsSum = LastOffsSum2 = 0;
00143       LastOffsSumsq = LastOffsSumsq2 = 0;
00144       return 0;
00145    }
00146 
00147 };
00148 
00149 
00150 
00151 
00152 
00153 int XrdClientReadAhead_slidingavg::GetReadAheadHint(long long offset, long len, long long &raoffset, long &ralen, long blksz) {
00154 
00155    if (!blksz) blksz = 128*1024;
00156 
00157    // Keep the sums up to date, together with the max array size and the sumsqs
00158    LastOffsSum += offset;
00159    LastOffsSum2 += offset;
00160    LastOffs.Push_back(offset);
00161 
00162    if (LastOffs.GetSize() >= 50) {
00163       LastOffsSum2 -= LastOffs[LastOffs.GetSize()-50];
00164    }
00165    if (LastOffs.GetSize() >= 1000) {
00166       LastOffsSum -= LastOffs[0];
00167    }
00168 
00169    long long lastavg = LastOffsSum / LastOffs.GetSize();
00170    long long lastavg2 = LastOffsSum2 / xrdmin(LastOffs.GetSize(), 50);
00171 
00172 
00173    // Now the approximations of the std deviation, shifted right by some positions to avoid overflows
00174    long long sqerr = (((offset >> 20) - (lastavg >> 20))*((offset >> 20) - (lastavg >> 20)));
00175    LastOffsSumsq += sqerr;
00176    long long sqerr2 = ( ((offset - lastavg2) >> 20) * ((offset - lastavg2) >> 20) );
00177    LastOffsSumsq2 += sqerr2;
00178 
00179    LastAvgApprox.Push_back(sqerr);
00180    LastAvgApprox2.Push_back(sqerr2);
00181 
00182    if (LastAvgApprox2.GetSize() >= 50) {
00183       LastOffsSumsq2 -= LastAvgApprox2[0];
00184       LastAvgApprox2.Erase(0);
00185    }
00186 
00187    if (LastAvgApprox.GetSize() >= 1000) {
00188       LastOffsSumsq -= LastAvgApprox[0];
00189       LastAvgApprox.Erase(0);
00190    }
00191 
00192    if (LastOffs.GetSize() >= 1000) {
00193       LastOffs.Erase(0);
00194    }
00195 
00196    long long stddevi = LastOffsSumsq / LastOffs.GetSize();
00197    long long stddevi2 = LastOffsSumsq2 / LastAvgApprox2.GetSize();
00198 
00199    //std::cerr << "offs:" << offset << " avg:" << lastavg << " avg2:" << lastavg2 << " devi:" << stddevi << " devi2:" << stddevi2;
00200 
00201    // To read ahead, we want at least a few samples
00202    //if ( LastOffs.GetSize() < 10 ) return 1;
00203 
00204    // If the more stable avg is usable, use it
00205    if ((stddevi << 20) < 3*RASize) {
00206       raoffset = xrdmax(RALast, lastavg - RASize/2);
00207 
00208       ralen = xrdmin(RASize,
00209                      lastavg + RASize/2 - raoffset);
00210 
00211       if (ralen > (1024*1024)) {
00212          TrimReadRequest(raoffset, ralen, RASize, blksz);
00213          RALast = raoffset + ralen;
00214          //std::cerr << " raoffs:" << raoffset << " ralen:" << ralen << " Got avg" << std::endl;
00215          return 0;
00216       }
00217       //std::cerr << std::endl;
00218    } else
00219       // If the less stable avg is usable, use it     
00220       if ((stddevi2 << 20) < 3*RASize) {
00221          raoffset = xrdmax(RALast, lastavg2 - RASize/2);
00222 
00223          ralen = xrdmin(RASize,
00224                         lastavg2 + RASize/2 - raoffset);
00225 
00226  
00227          if (ralen > (1024*1024)) {
00228             TrimReadRequest(raoffset, ralen, RASize, blksz);
00229             RALast = raoffset + ralen;
00230             //std::cerr << " raoffs:" << raoffset << " ralen:" << ralen  << " Got avg2" << std::endl;
00231             return 0;
00232          }
00233          //std::cerr << std::endl;
00234       }
00235 
00236    //std::cerr << std::endl;
00237    return 1;
00238 
00239    
00240 };
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 // ------------------------------------------------------
00253 
00254 XrdClientReadAheadMgr *XrdClientReadAheadMgr::CreateReadAheadMgr(XrdClient_RAStrategy strategy) {
00255    XrdClientReadAheadMgr *ramgr = 0;
00256 
00257    switch (strategy) {
00258 
00259    case RAStr_none:
00260       break;
00261 
00262    case RAStr_pureseq: {
00263          ramgr = new XrdClientReadAhead_pureseq();
00264          break;
00265       }
00266    case RAStr_SlidingAvg: {
00267          ramgr = new XrdClientReadAhead_slidingavg();
00268          break;
00269       }
00270      
00271    }
00272 
00273    if (ramgr) ramgr->currstrategy = strategy;
00274    return ramgr;
00275 }

Generated on Tue Jul 5 14:46:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1