summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2004-08-25 01:47:55 -0400
committerJohn Wiegley <johnw@newartisans.com>2004-08-25 01:47:55 -0400
commit6febfc3b4cd6b374479f34070da9a772f9ff5699 (patch)
tree941ff96e45bd412003be1dab05baf1f9404bf001
parentc6860970f27ed1f0d9b9543da46ffffa5c20e8f6 (diff)
downloadfork-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.cc37
-rw-r--r--amount.h2
-rw-r--r--binary.cc102
-rw-r--r--binary.h4
-rw-r--r--ledger.cc2
-rw-r--r--ledger.h14
6 files changed, 112 insertions, 49 deletions
diff --git a/amount.cc b/amount.cc
index 8915e91f..49762d17 100644
--- a/amount.cc
+++ b/amount.cc
@@ -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);
diff --git a/amount.h b/amount.h
index 9edbd9fd..d6fb2265 100644
--- a/amount.h
+++ b/amount.h
@@ -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);
diff --git a/binary.cc b/binary.cc
index a5a2e4e0..f6135dac 100644
--- a/binary.cc
+++ b/binary.cc
@@ -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
diff --git a/binary.h b/binary.h
index a1ab60c2..187cdcb8 100644
--- a/binary.h
+++ b/binary.h
@@ -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,
diff --git a/ledger.cc b/ledger.cc
index 91b1985c..66fbe9c7 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -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;
diff --git a/ledger.h b/ledger.h
index ed0b6101..2e24201a 100644
--- a/ledger.h
+++ b/ledger.h
@@ -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) {