diff options
author | John Wiegley <johnw@newartisans.com> | 2004-08-25 01:47:55 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2004-08-25 01:47:55 -0400 |
commit | 6febfc3b4cd6b374479f34070da9a772f9ff5699 (patch) | |
tree | 941ff96e45bd412003be1dab05baf1f9404bf001 | |
parent | c6860970f27ed1f0d9b9543da46ffffa5c20e8f6 (diff) | |
download | fork-ledger-6febfc3b4cd6b374479f34070da9a772f9ff5699.tar.gz fork-ledger-6febfc3b4cd6b374479f34070da9a772f9ff5699.tar.bz2 fork-ledger-6febfc3b4cd6b374479f34070da9a772f9ff5699.zip |
Bulk alloc bigints in the binary reader; this gains another 20%
-rw-r--r-- | amount.cc | 37 | ||||
-rw-r--r-- | amount.h | 2 | ||||
-rw-r--r-- | binary.cc | 102 | ||||
-rw-r--r-- | binary.h | 4 | ||||
-rw-r--r-- | ledger.cc | 2 | ||||
-rw-r--r-- | ledger.h | 14 |
6 files changed, 112 insertions, 49 deletions
@@ -11,23 +11,26 @@ namespace ledger { +#define BIGINT_BULK_ALLOC 0x0001 + class amount_t::bigint_t { public: - mpz_t val; - unsigned int prec; - unsigned int ref; - unsigned int index; + mpz_t val; + unsigned short prec; + unsigned short flags; + unsigned int ref; + unsigned int index; - bigint_t() : prec(0), ref(1), index(0) { + bigint_t() : prec(0), flags(0), ref(1), index(0) { DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init(val); } - bigint_t(mpz_t _val) : prec(0), ref(1), index(0) { + bigint_t(mpz_t _val) : prec(0), flags(0), ref(1), index(0) { DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init_set(val, _val); } bigint_t(const bigint_t& other) - : prec(other.prec), ref(1), index(0) { + : prec(other.prec), flags(0), ref(1), index(0) { DEBUG_PRINT("ledger.memory.ctors", "ctor amount_t::bigint_t"); mpz_init_set(val, other.val); } @@ -38,6 +41,10 @@ class amount_t::bigint_t { } }; +unsigned int sizeof_bigint_t() { + return sizeof(amount_t::bigint_t); +} + #define MPZ(x) ((x)->val) static mpz_t temp; @@ -177,8 +184,12 @@ amount_t::amount_t(const double value) void amount_t::_release() { - if (--quantity->ref == 0) - delete quantity; + if (--quantity->ref == 0) { + if (! (quantity->flags & BIGINT_BULK_ALLOC)) + delete quantity; + else + quantity->~bigint_t(); + } } void amount_t::_init() @@ -886,6 +897,7 @@ void amount_t::write_quantity(std::ostream& out) const if (quantity->index == 0) { quantity->index = ++index; + bigints_count++; byte = 1; out.write(&byte, sizeof(byte)); @@ -925,8 +937,8 @@ void amount_t::read_quantity(std::istream& in) return; if (byte == 1) { - quantity = new bigint_t; - bigints.push_back(quantity); + quantity = new(bigints_next++) bigint_t; + quantity->flags |= BIGINT_BULK_ALLOC; unsigned short len; in.read((char *)&len, sizeof(len)); @@ -942,8 +954,7 @@ void amount_t::read_quantity(std::istream& in) } else { unsigned int index; in.read((char *)&index, sizeof(index)); - assert(index <= bigints.size()); - quantity = bigints[index - 1]; + quantity = bigints + (index - 1); quantity->ref++; DEBUG_PRINT("ledger.amount.bigint-show", "bigint " << quantity << " ++ref " << quantity->ref); @@ -170,6 +170,8 @@ class amount_t friend std::istream& operator>>(std::istream& in, amount_t& amt); }; +unsigned int sizeof_bigint_t(); + void parse_quantity(std::istream& in, std::string& value); void parse_commodity(std::istream& in, std::string& symbol); @@ -9,17 +9,19 @@ namespace ledger { const unsigned long binary_magic_number = 0xFFEED765; -static const unsigned long format_version = 0x00020015; +static const unsigned long format_version = 0x00020017; -static account_t ** accounts; -static account_t ** accounts_next; -static unsigned int account_index; +static account_t ** accounts; +static account_t ** accounts_next; +static unsigned int account_index; -static commodity_t ** commodities; -static commodity_t ** commodities_next; -static unsigned int commodity_index; +static commodity_t ** commodities; +static commodity_t ** commodities_next; +static unsigned int commodity_index; -std::deque<amount_t::bigint_t *> bigints; +amount_t::bigint_t * bigints; +amount_t::bigint_t * bigints_next; +unsigned int bigints_count; #if DEBUG_LEVEL >= ALPHA #define read_binary_guard(in, id) { \ @@ -135,6 +137,7 @@ inline void read_binary_transaction(std::istream& in, transaction_t * xact, xact->cost = NULL; } read_binary_number(in, xact->flags); + xact->flags |= TRANSACTION_BULK_ALLOC; init_binary_string(string_pool, &xact->note); xact->data = NULL; @@ -236,6 +239,9 @@ unsigned int read_binary_journal(std::istream& in, account_index = commodity_index = 0; + // Read in the files that participated in this journal, so that they + // can be checked for changes on reading. + if (! file.empty()) { for (unsigned short i = 0, count = read_binary_number<unsigned short>(in); @@ -256,19 +262,13 @@ unsigned int read_binary_journal(std::istream& in, } } + // Read in the accounts + account_t::ident_t a_count = read_binary_number<account_t::ident_t>(in); accounts = accounts_next = new (account_t *)[a_count]; journal->master = read_binary_account(in, master); - commodity_t::ident_t c_count = read_binary_number<commodity_t::ident_t>(in); - commodities = commodities_next = new (commodity_t *)[c_count]; - for (commodity_t::ident_t i = 0; i < c_count; i++) { - commodity_t * commodity = read_binary_commodity(in); - std::pair<commodities_map::iterator, bool> result - = commodity_t::commodities.insert(commodities_pair(commodity->symbol, - commodity)); - assert(result.second || master); - } + // Read in the string pool unsigned long string_size = read_binary_number<unsigned long>(in); @@ -277,20 +277,39 @@ unsigned int read_binary_journal(std::istream& in, in.read(string_pool, string_size); - // Memory needed for the entries and transactions is allocated in + // Allocate the memory needed for the entries and transactions in // one large block, which is then chopped up and custom constructed - // as necessary. This reduces binary load time by 20%! + // as necessary. - unsigned long count = read_binary_number<unsigned long>(in); - unsigned long xact_count = read_binary_number<unsigned long>(in); + unsigned long count = read_binary_number<unsigned long>(in); + unsigned long xact_count = read_binary_number<unsigned long>(in); + unsigned long bigint_count = read_binary_number<unsigned long>(in); std::size_t pool_size = (sizeof(entry_t) * count + - sizeof(transaction_t) * xact_count); + sizeof(transaction_t) * xact_count + + sizeof_bigint_t() * bigint_count); char * item_pool = new char[pool_size]; entry_t * entry_pool = (entry_t *) item_pool; transaction_t * xact_pool = (transaction_t *) (item_pool + sizeof(entry_t) * count); + bigints = bigints_next + = (amount_t::bigint_t *) (item_pool + sizeof(entry_t) * count + + sizeof(transaction_t) * xact_count); + + // Read in the commodities + + commodity_t::ident_t c_count = read_binary_number<commodity_t::ident_t>(in); + commodities = commodities_next = new (commodity_t *)[c_count]; + for (commodity_t::ident_t i = 0; i < c_count; i++) { + commodity_t * commodity = read_binary_commodity(in); + std::pair<commodities_map::iterator, bool> result + = commodity_t::commodities.insert(commodities_pair(commodity->symbol, + commodity)); + assert(result.second || master); + } + + // Read in the entries and transactions for (unsigned long i = 0; i < count; i++) { read_binary_entry(in, entry_pool, xact_pool, string_next); @@ -299,6 +318,8 @@ unsigned int read_binary_journal(std::istream& in, assert(string_next == string_pool + string_size); + // Clean up and return the number of entries read + journal->item_pool = item_pool; journal->item_pool_end = item_pool + pool_size; @@ -306,8 +327,6 @@ unsigned int read_binary_journal(std::istream& in, delete[] commodities; delete[] string_pool; - bigints.clear(); - return count; } @@ -460,6 +479,9 @@ void write_binary_journal(std::ostream& out, journal_t * journal, write_binary_number(out, binary_magic_number); write_binary_number(out, format_version); + // Write out the files that participated in this journal, so that + // they can be checked for changes on reading. + if (! files) { write_binary_number<unsigned short>(out, 0); } else { @@ -474,15 +496,12 @@ void write_binary_journal(std::ostream& out, journal_t * journal, } } + // Write out the accounts + write_binary_number<account_t::ident_t>(out, count_accounts(journal->master)); write_binary_account(out, journal->master); - write_binary_number<commodity_t::ident_t>(out, commodity_t::commodities.size() - 1); - for (commodities_map::const_iterator i = commodity_t::commodities.begin(); - i != commodity_t::commodities.end(); - i++) - if (! (*i).first.empty()) - write_binary_commodity(out, (*i).second); + // Calculate some sizes unsigned long xact_count = 0; unsigned long string_size = 0; @@ -506,6 +525,8 @@ void write_binary_journal(std::ostream& out, journal_t * journal, } } + // Write out the string pool + write_binary_number<unsigned long>(out, string_size); for (entries_list::const_iterator i = journal->entries.begin(); @@ -520,13 +541,34 @@ void write_binary_journal(std::ostream& out, journal_t * journal, write_binary_string(out, (*j)->note); } + // Write out the number of entries, transactions, and amounts + write_binary_number<unsigned long>(out, journal->entries.size()); write_binary_number<unsigned long>(out, xact_count); + std::ostream::pos_type here = out.tellp(); + write_binary_number<unsigned long>(out, 0); + bigints_count = 0; + + // Write out the commodities + + write_binary_number<commodity_t::ident_t>(out, commodity_t::commodities.size() - 1); + for (commodities_map::const_iterator i = commodity_t::commodities.begin(); + i != commodity_t::commodities.end(); + i++) + if (! (*i).first.empty()) + write_binary_commodity(out, (*i).second); + + // Write out the entries and transactions for (entries_list::const_iterator i = journal->entries.begin(); i != journal->entries.end(); i++) write_binary_entry(out, *i); + + // Back-patch the count for amounts + + out.seekp(here); + write_binary_number<unsigned long>(out, bigints_count); } } // namespace ledger @@ -18,7 +18,9 @@ class binary_parser_t : public parser_t const std::string * original_file = NULL); }; -extern std::deque<amount_t::bigint_t *> bigints; +extern amount_t::bigint_t * bigints; +extern amount_t::bigint_t * bigints_next; +extern unsigned int bigints_count; void write_binary_journal(std::ostream& out, journal_t * journal, @@ -83,6 +83,8 @@ journal_t::~journal_t() if (! item_pool || ((char *) *i) < item_pool || ((char *) *i) >= item_pool_end) delete *i; + else + (*i)->~entry_t(); if (item_pool) delete[] item_pool; @@ -22,10 +22,11 @@ namespace ledger { // These flags persist with the object -#define TRANSACTION_NORMAL 0x0000 -#define TRANSACTION_VIRTUAL 0x0001 -#define TRANSACTION_BALANCE 0x0002 -#define TRANSACTION_AUTO 0x0004 +#define TRANSACTION_NORMAL 0x0000 +#define TRANSACTION_VIRTUAL 0x0001 +#define TRANSACTION_BALANCE 0x0002 +#define TRANSACTION_AUTO 0x0004 +#define TRANSACTION_BULK_ALLOC 0x0008 class entry_t; class account_t; @@ -84,7 +85,10 @@ class entry_t for (transactions_list::iterator i = transactions.begin(); i != transactions.end(); i++) - delete *i; + if (! ((*i)->flags & TRANSACTION_BULK_ALLOC)) + delete *i; + else + (*i)->~transaction_t(); } void add_transaction(transaction_t * xact) { |