Ticket #325: 0001-Refactor-zlib-usage-in-FlintTable-to-avoid-reallocat.patch

File 0001-Refactor-zlib-usage-in-FlintTable-to-avoid-reallocat.patch, 9.5 KB (added by Todd Lipcon, 16 years ago)
  • backends/flint/flint_table.cc

    From 16e316c9f0686b4b20c217d765260342a5f5a7b9 Mon Sep 17 00:00:00 2001
    From: Todd Lipcon <todd@lipcon.org>
    Date: Tue, 3 Feb 2009 00:13:03 -0500
    Subject: [PATCH] Refactor zlib usage in FlintTable to avoid reallocations of z_stream object
    
    ---
     backends/flint/flint_table.cc |  198 +++++++++++++++++++++++++----------------
     backends/flint/flint_table.h  |    8 ++
     2 files changed, 128 insertions(+), 78 deletions(-)
    
    diff --git a/backends/flint/flint_table.cc b/backends/flint/flint_table.cc
    index 16c719c..cfc2a61 100644
    a b FlintTable::add(const string &key, string tag, bool already_compressed)  
    10371037        CompileTimeAssert(DONT_COMPRESS != Z_RLE);
    10381038#endif
    10391039
    1040         z_stream stream;
    1041 
    1042         stream.zalloc = reinterpret_cast<alloc_func>(0);
    1043         stream.zfree = reinterpret_cast<free_func>(0);
    1044         stream.opaque = (voidpf)0;
    1045 
    1046         // -15 means raw deflate with 32K LZ77 window (largest)
    1047         // memLevel 9 is the highest (8 is default)
    1048         int err;
    1049         err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
    1050                            compress_strategy);
    1051         if (err != Z_OK) {
    1052             if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1053             string msg = "deflateInit2 failed";
    1054             if (stream.msg) {
    1055                 msg += " (";
    1056                 msg += stream.msg;
    1057                 msg += ')';
    1058             }
    1059             throw Xapian::DatabaseError(msg);
    1060         }
     1040        lazy_alloc_deflate_zstream();
     1041        deflateReset(deflate_zstream);
    10611042
    1062         stream.next_in = (Bytef *)const_cast<char *>(tag.data());
    1063         stream.avail_in = (uInt)tag.size();
     1043        deflate_zstream->next_in = (Bytef *)const_cast<char *>(tag.data());
     1044        deflate_zstream->avail_in = (uInt)tag.size();
    10641045
    10651046        // If compressed size is >= tag.size(), we don't want to compress.
    10661047        unsigned long blk_len = tag.size() - 1;
    10671048        unsigned char * blk = new unsigned char[blk_len];
    1068         stream.next_out = blk;
    1069         stream.avail_out = (uInt)blk_len;
     1049        deflate_zstream->next_out = blk;
     1050        deflate_zstream->avail_out = (uInt)blk_len;
    10701051
    1071         err = deflate(&stream, Z_FINISH);
     1052        int err = deflate(deflate_zstream, Z_FINISH);
    10721053        if (err == Z_STREAM_END) {
    10731054            // If deflate succeeded, then the output was at least one byte
    10741055            // smaller than the input.
    1075             tag.assign(reinterpret_cast<const char *>(blk), stream.total_out);
     1056            tag.assign(reinterpret_cast<const char *>(blk), deflate_zstream->total_out);
    10761057            compressed = true;
    1077             err = deflateEnd(&stream);
    1078             if (err != Z_OK) {
    1079                 string msg = "deflateEnd failed";
    1080                 if (stream.msg) {
    1081                     msg += " (";
    1082                     msg += stream.msg;
    1083                     msg += ')';
    1084                 }
    1085                 throw Xapian::DatabaseError(msg);
    1086             }
    10871058        } else {
    1088             // Deflate failed - presumably the data wasn't compressible.
    1089             (void)deflateEnd(&stream);
    10901059        }
    10911060
    10921061        delete [] blk;
    FlintTable::read_tag(Cursor_ * C_, string *tag, bool keep_compressed) const  
    12711240
    12721241    Bytef buf[8192];
    12731242
    1274     z_stream stream;
    1275     stream.next_out = buf;
    1276     stream.avail_out = (uInt)sizeof(buf);
     1243    inflateReset(inflate_zstream);
    12771244
    1278     stream.zalloc = reinterpret_cast<alloc_func>(0);
    1279     stream.zfree = reinterpret_cast<free_func>(0);
     1245    inflate_zstream->next_out = buf;
     1246    inflate_zstream->avail_out = (uInt)sizeof(buf);
    12801247
    1281     stream.next_in = Z_NULL;
    1282     stream.avail_in = 0;
    1283 
    1284     int err = inflateInit2(&stream, -15);
    1285     if (err != Z_OK) {
    1286         if (err == Z_MEM_ERROR) throw std::bad_alloc();
    1287         string msg = "inflateInit2 failed";
    1288         if (stream.msg) {
    1289             msg += " (";
    1290             msg += stream.msg;
    1291             msg += ')';
    1292         }
    1293         throw Xapian::DatabaseError(msg);
    1294     }
    1295 
    1296     stream.next_in = (Bytef*)const_cast<char *>(tag->data());
    1297     stream.avail_in = (uInt)tag->size();
     1248    inflate_zstream->next_in = (Bytef*)const_cast<char *>(tag->data());
     1249    inflate_zstream->avail_in = (uInt)tag->size();
    12981250
     1251    int err;
    12991252    while (err != Z_STREAM_END) {
    1300         stream.next_out = buf;
    1301         stream.avail_out = (uInt)sizeof(buf);
    1302         err = inflate(&stream, Z_SYNC_FLUSH);
    1303         if (err == Z_BUF_ERROR && stream.avail_in == 0) {
    1304             DEBUGLINE(DB, "Z_BUF_ERROR - faking checksum of " << stream.adler);
     1253        inflate_zstream->next_out = buf;
     1254        inflate_zstream->avail_out = (uInt)sizeof(buf);
     1255        err = inflate(inflate_zstream, Z_SYNC_FLUSH);
     1256        if (err == Z_BUF_ERROR && inflate_zstream->avail_in == 0) {
     1257            DEBUGLINE(DB, "Z_BUF_ERROR - faking checksum of " << inflate_zstream->adler);
    13051258            Bytef header2[4];
    1306             setint4(header2, 0, stream.adler);
    1307             stream.next_in = header2;
    1308             stream.avail_in = 4;
    1309             err = inflate(&stream, Z_SYNC_FLUSH);
     1259            setint4(header2, 0, inflate_zstream->adler);
     1260            inflate_zstream->next_in = header2;
     1261            inflate_zstream->avail_in = 4;
     1262            err = inflate(inflate_zstream, Z_SYNC_FLUSH);
    13101263            if (err == Z_STREAM_END) break;
    13111264        }
    13121265
    13131266        if (err != Z_OK && err != Z_STREAM_END) {
    13141267            if (err == Z_MEM_ERROR) throw std::bad_alloc();
    13151268            string msg = "inflate failed";
    1316             if (stream.msg) {
     1269            if (inflate_zstream->msg) {
    13171270                msg += " (";
    1318                 msg += stream.msg;
     1271                msg += inflate_zstream->msg;
    13191272                msg += ')';
    13201273            }
    13211274            throw Xapian::DatabaseError(msg);
    13221275        }
    13231276
    13241277        utag.append(reinterpret_cast<const char *>(buf),
    1325                     stream.next_out - buf);
     1278                    inflate_zstream->next_out - buf);
    13261279    }
    1327     if (utag.size() != stream.total_out) {
     1280    if (utag.size() != inflate_zstream->total_out) {
    13281281        string msg = "compressed tag didn't expand to the expected size: ";
    13291282        msg += om_tostring(utag.size());
    13301283        msg += " != ";
    13311284        // OpenBSD's zlib.h uses off_t instead of uLong for total_out.
    1332         msg += om_tostring((size_t)stream.total_out);
     1285        msg += om_tostring((size_t)inflate_zstream->total_out);
    13331286        throw Xapian::DatabaseCorruptError(msg);
    13341287    }
    13351288
    1336     err = inflateEnd(&stream);
    1337     if (err != Z_OK) abort();
    1338 
    13391289    swap(*tag, utag);
    13401290
    13411291    return false;
    FlintTable::FlintTable(string path_, bool readonly_,  
    16121562          writable(!readonly_),
    16131563          split_p(0),
    16141564          compress_strategy(compress_strategy_),
     1565          deflate_zstream(NULL),
     1566          inflate_zstream(NULL),
    16151567          lazy(lazy_)
    16161568{
    16171569    DEBUGCALL(DB, void, "FlintTable::FlintTable",
    16181570              tablename_ << "," << path_ << ", " << readonly_ << ", " <<
    16191571              compress_strategy_ << ", " << lazy_);
     1572
     1573    // We want to do this lazily, but the read functions are const so we can't :(
     1574    lazy_alloc_inflate_zstream();
     1575
     1576}
     1577
     1578
     1579void
     1580FlintTable::lazy_alloc_deflate_zstream() {
     1581    if (deflate_zstream)
     1582        return;
     1583
     1584    deflate_zstream = new z_stream;
     1585       
     1586    deflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1587    deflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1588    deflate_zstream->opaque = (voidpf)0;
     1589
     1590    // -15 means raw deflate with 32K LZ77 window (largest)
     1591    // memLevel 9 is the highest (8 is default)
     1592    int err;
     1593    err = deflateInit2(deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9,
     1594                       compress_strategy);
     1595    if (err != Z_OK) {
     1596        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1597        string msg = "deflateInit2 failed. err = " + err;
     1598        if (deflate_zstream->msg) {
     1599            msg += " (";
     1600            msg += deflate_zstream->msg;
     1601            msg += ')';
     1602        }
     1603        throw Xapian::DatabaseError(msg);
     1604    }
     1605}
     1606
     1607
     1608void
     1609FlintTable::lazy_alloc_inflate_zstream() {
     1610    if (inflate_zstream)
     1611        return;
     1612
     1613    inflate_zstream = new z_stream;
     1614
     1615    inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
     1616    inflate_zstream->zfree = reinterpret_cast<free_func>(0);
     1617
     1618    inflate_zstream->next_in = Z_NULL;
     1619    inflate_zstream->avail_in = 0;
     1620
     1621    int err = inflateInit2(inflate_zstream, -15);
     1622    if (err != Z_OK) {
     1623        if (err == Z_MEM_ERROR) throw std::bad_alloc();
     1624        string msg = "inflateInit2 failed";
     1625        if (inflate_zstream->msg) {
     1626            msg += " (";
     1627            msg += inflate_zstream->msg;
     1628            msg += ')';
     1629        }
     1630        throw Xapian::DatabaseError(msg);
     1631    }
    16201632}
    16211633
    16221634bool
    FlintTable::create_and_open(unsigned int block_size_)  
    16991711FlintTable::~FlintTable() {
    17001712    DEBUGCALL(DB, void, "FlintTable::~FlintTable", "");
    17011713    FlintTable::close();
     1714
     1715    if (deflate_zstream) {
     1716        int err = deflateEnd(deflate_zstream);
     1717        if (err != Z_OK) {
     1718            string msg = "deflateEnd failed. err = " + err;
     1719            if (deflate_zstream->msg) {
     1720                msg += " (";
     1721                msg += deflate_zstream->msg;
     1722                msg += ')';
     1723            }
     1724            delete deflate_zstream;
     1725            throw Xapian::DatabaseError(msg);
     1726        }
     1727        delete deflate_zstream;       
     1728    }
     1729
     1730    if (inflate_zstream) {
     1731        int err = inflateEnd(inflate_zstream);
     1732        if (err != Z_OK) {
     1733            string msg = "inflateEnd failed. err = " + err;
     1734            if (inflate_zstream->msg) {
     1735                msg += " (";
     1736                msg += inflate_zstream->msg;
     1737                msg += ')';
     1738            }
     1739            delete inflate_zstream;
     1740            throw Xapian::DatabaseError(msg);
     1741        }
     1742        delete inflate_zstream;
     1743    }
    17021744}
    17031745
    17041746void FlintTable::close(bool permanent) {
  • backends/flint/flint_table.h

    diff --git a/backends/flint/flint_table.h b/backends/flint/flint_table.h
    index e1e2d32..d51d0e0 100644
    a b class XAPIAN_VISIBILITY_DEFAULT FlintTable {  
    587587           return (base_letter == 'A') ? 'B' : 'A';
    588588        }
    589589
     590    void lazy_alloc_deflate_zstream();
     591    void lazy_alloc_inflate_zstream();
     592
    590593        /** revision number of the opened B-tree. */
    591594        flint_revision_number_t revision_number;
    592595
    class XAPIAN_VISIBILITY_DEFAULT FlintTable {  
    705708         *  Z_RLE. */
    706709        int compress_strategy;
    707710
     711    /** Zlib state object */
     712    z_stream *deflate_zstream;
     713    z_stream *inflate_zstream;
     714
     715
    708716        /// If true, don't create the table until it's needed.
    709717        bool lazy;
    710718