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 , 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) 1037 1037 CompileTimeAssert(DONT_COMPRESS != Z_RLE); 1038 1038 #endif 1039 1039 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); 1061 1042 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(); 1064 1045 1065 1046 // If compressed size is >= tag.size(), we don't want to compress. 1066 1047 unsigned long blk_len = tag.size() - 1; 1067 1048 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; 1070 1051 1071 err = deflate(&stream, Z_FINISH);1052 int err = deflate(deflate_zstream, Z_FINISH); 1072 1053 if (err == Z_STREAM_END) { 1073 1054 // If deflate succeeded, then the output was at least one byte 1074 1055 // 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); 1076 1057 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 }1087 1058 } else { 1088 // Deflate failed - presumably the data wasn't compressible.1089 (void)deflateEnd(&stream);1090 1059 } 1091 1060 1092 1061 delete [] blk; … … FlintTable::read_tag(Cursor_ * C_, string *tag, bool keep_compressed) const 1271 1240 1272 1241 Bytef buf[8192]; 1273 1242 1274 z_stream stream; 1275 stream.next_out = buf; 1276 stream.avail_out = (uInt)sizeof(buf); 1243 inflateReset(inflate_zstream); 1277 1244 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); 1280 1247 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(); 1298 1250 1251 int err; 1299 1252 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); 1305 1258 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); 1310 1263 if (err == Z_STREAM_END) break; 1311 1264 } 1312 1265 1313 1266 if (err != Z_OK && err != Z_STREAM_END) { 1314 1267 if (err == Z_MEM_ERROR) throw std::bad_alloc(); 1315 1268 string msg = "inflate failed"; 1316 if ( stream.msg) {1269 if (inflate_zstream->msg) { 1317 1270 msg += " ("; 1318 msg += stream.msg;1271 msg += inflate_zstream->msg; 1319 1272 msg += ')'; 1320 1273 } 1321 1274 throw Xapian::DatabaseError(msg); 1322 1275 } 1323 1276 1324 1277 utag.append(reinterpret_cast<const char *>(buf), 1325 stream.next_out - buf);1278 inflate_zstream->next_out - buf); 1326 1279 } 1327 if (utag.size() != stream.total_out) {1280 if (utag.size() != inflate_zstream->total_out) { 1328 1281 string msg = "compressed tag didn't expand to the expected size: "; 1329 1282 msg += om_tostring(utag.size()); 1330 1283 msg += " != "; 1331 1284 // 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); 1333 1286 throw Xapian::DatabaseCorruptError(msg); 1334 1287 } 1335 1288 1336 err = inflateEnd(&stream);1337 if (err != Z_OK) abort();1338 1339 1289 swap(*tag, utag); 1340 1290 1341 1291 return false; … … FlintTable::FlintTable(string path_, bool readonly_, 1612 1562 writable(!readonly_), 1613 1563 split_p(0), 1614 1564 compress_strategy(compress_strategy_), 1565 deflate_zstream(NULL), 1566 inflate_zstream(NULL), 1615 1567 lazy(lazy_) 1616 1568 { 1617 1569 DEBUGCALL(DB, void, "FlintTable::FlintTable", 1618 1570 tablename_ << "," << path_ << ", " << readonly_ << ", " << 1619 1571 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 1579 void 1580 FlintTable::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 1608 void 1609 FlintTable::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 } 1620 1632 } 1621 1633 1622 1634 bool … … FlintTable::create_and_open(unsigned int block_size_) 1699 1711 FlintTable::~FlintTable() { 1700 1712 DEBUGCALL(DB, void, "FlintTable::~FlintTable", ""); 1701 1713 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 } 1702 1744 } 1703 1745 1704 1746 void 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 { 587 587 return (base_letter == 'A') ? 'B' : 'A'; 588 588 } 589 589 590 void lazy_alloc_deflate_zstream(); 591 void lazy_alloc_inflate_zstream(); 592 590 593 /** revision number of the opened B-tree. */ 591 594 flint_revision_number_t revision_number; 592 595 … … class XAPIAN_VISIBILITY_DEFAULT FlintTable { 705 708 * Z_RLE. */ 706 709 int compress_strategy; 707 710 711 /** Zlib state object */ 712 z_stream *deflate_zstream; 713 z_stream *inflate_zstream; 714 715 708 716 /// If true, don't create the table until it's needed. 709 717 bool lazy; 710 718