change to binary loading that increases speed by another 20%

This commit is contained in:
John Wiegley 2004-08-23 07:23:33 -04:00
parent 1091f0d07b
commit b85a536be7
4 changed files with 107 additions and 24 deletions

View file

@ -5,6 +5,8 @@
namespace ledger {
#ifdef DO_CLEANUP
account_t::~account_t()
{
DEBUG_PRINT("ledger.memory.ctors", "dtor account_t");
@ -16,6 +18,8 @@ account_t::~account_t()
delete (*i).second;
}
#endif // DO_CLEANUP
account_t * account_t::find_account(const std::string& name,
const bool auto_create)
{

101
binary.cc
View file

@ -9,7 +9,7 @@
namespace ledger {
const unsigned long binary_magic_number = 0xFFEED765;
static const unsigned long format_version = 0x00020012;
static const unsigned long format_version = 0x00020013;
bool binary_parser_t::test(std::istream& in) const
{
@ -75,6 +75,33 @@ inline void read_binary_string(std::istream& in, std::string& str)
read_binary_guard(in, 0x3002);
}
inline void init_binary_string(std::istream& in, std::string * str)
{
read_binary_guard(in, 0x3001);
unsigned char len;
read_binary_number(in, len);
if (len == 0xff) {
unsigned short slen;
read_binary_number(in, slen);
char * buf = new char[slen + 1];
in.read(buf, slen);
buf[slen] = '\0';
new(str) std::string(buf);
delete[] buf;
}
else if (len) {
char buf[256];
in.read(buf, len);
buf[len] = '\0';
new(str) std::string(buf);
} else {
new(str) std::string("");
}
read_binary_guard(in, 0x3002);
}
inline std::string read_binary_string(std::istream& in)
{
std::string temp;
@ -82,7 +109,7 @@ inline std::string read_binary_string(std::istream& in)
return temp;
}
void read_binary_amount(std::istream& in, amount_t& amt)
inline void read_binary_amount(std::istream& in, amount_t& amt)
{
commodity_t::ident_t ident;
read_binary_number(in, ident);
@ -94,44 +121,46 @@ void read_binary_amount(std::istream& in, amount_t& amt)
amt.read_quantity(in);
}
transaction_t * read_binary_transaction(std::istream& in, entry_t * entry)
inline void read_binary_transaction(std::istream& in, transaction_t * xact)
{
transaction_t * xact = new transaction_t(NULL);
xact->account = accounts[read_binary_number<account_t::ident_t>(in) - 1];
xact->account->add_transaction(xact);
new ((amount_t *) &xact->amount) amount_t;
read_binary_amount(in, xact->amount);
if (read_binary_number<char>(in) == 1) {
xact->cost = new amount_t;
read_binary_amount(in, *xact->cost);
} else {
xact->cost = NULL;
}
read_binary_number(in, xact->flags);
read_binary_string(in, xact->note);
init_binary_string(in, &xact->note);
return xact;
xact->data = NULL;
}
entry_t * read_binary_entry(std::istream& in, journal_t * journal)
inline void read_binary_entry(std::istream& in, entry_t * entry,
transaction_t *& xact_pool, journal_t * journal)
{
entry_t * entry = new entry_t;
read_binary_number(in, entry->date);
read_binary_number(in, entry->state);
read_binary_string(in, entry->code);
read_binary_string(in, entry->payee);
init_binary_string(in, &entry->code);
init_binary_string(in, &entry->payee);
new(&entry->transactions) transactions_list;
for (unsigned long i = 0, count = read_binary_number<unsigned long>(in);
i < count;
i++) {
transaction_t * xact = read_binary_transaction(in, entry);
entry->add_transaction(xact);
read_binary_transaction(in, xact_pool);
xact_pool->entry = entry;
entry->transactions.push_back(xact_pool++);
}
return entry;
}
commodity_t * read_binary_commodity(std::istream& in)
inline commodity_t * read_binary_commodity(std::istream& in)
{
commodity_t * commodity = new commodity_t;
commodities.push_back(commodity);
@ -161,6 +190,7 @@ commodity_t * read_binary_commodity(std::istream& in)
return commodity;
}
inline
account_t * read_binary_account(std::istream& in, account_t * master = NULL)
{
account_t * acct = new account_t(NULL);
@ -246,17 +276,34 @@ unsigned int read_binary_journal(std::istream& in,
assert(result.second || master);
}
unsigned int count = read_binary_number<unsigned long>(in);
for (unsigned long i = 0;
i < count;
i++) {
entry_t * entry = read_binary_entry(in, journal);
journal->entries.push_back(entry);
unsigned long count = read_binary_number<unsigned long>(in);
unsigned long xact_count = read_binary_number<unsigned long>(in);
// Memory needed for the entries and transactions is allocated in
// one large block, which is then chopped up and custom constructed
// as necessary. This reduces binary load time by 20%!
std::size_t pool_size = (sizeof(entry_t) * count +
sizeof(transaction_t) * xact_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);
for (unsigned long i = 0; i < count; i++) {
read_binary_entry(in, entry_pool, xact_pool, journal);
journal->entries.push_back(entry_pool++);
}
#ifdef DO_CLEANUP
journal->item_pool = item_pool;
journal->item_pool_end = item_pool + pool_size;
accounts.clear();
commodities.clear();
bigints.clear();
#endif
return count;
}
@ -414,7 +461,15 @@ void write_binary_journal(std::ostream& out, journal_t * journal,
if (! (*i).first.empty())
write_binary_commodity(out, (*i).second);
unsigned long xact_count = 0;
for (entries_list::const_iterator i = journal->entries.begin();
i != journal->entries.end();
i++)
xact_count += (*i)->transactions.size();
write_binary_number<unsigned long>(out, journal->entries.size());
write_binary_number<unsigned long>(out, xact_count);
for (entries_list::const_iterator i = journal->entries.begin();
i != journal->entries.end();
i++)

View file

@ -8,6 +8,8 @@ namespace ledger {
const std::string version = "2.0b";
#ifdef DO_CLEANUP
journal_t::~journal_t()
{
DEBUG_PRINT("ledger.memory.dtors", "dtor journal_t");
@ -20,9 +22,16 @@ journal_t::~journal_t()
for (entries_list::iterator i = entries.begin();
i != entries.end();
i++)
delete *i;
if (! item_pool ||
((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
delete *i;
if (item_pool)
delete[] item_pool;
}
#endif // DO_CLEANUP
bool journal_t::add_entry(entry_t * entry)
{
entries.push_back(entry);

View file

@ -54,11 +54,13 @@ class transaction_t
cost(NULL), flags(_flags), note(_note), data(NULL) {
}
#ifdef DO_CLEANUP
~transaction_t() {
//assert(! data);
if (cost)
delete cost;
}
#endif
};
@ -78,12 +80,14 @@ class entry_t
transactions_list transactions;
entry_t() : date(-1), state(UNCLEARED) {}
#ifdef DO_CLEANUP
~entry_t() {
for (transactions_list::iterator i = transactions.begin();
i != transactions.end();
i++)
delete *i;
}
#endif
void add_transaction(transaction_t * xact) {
xact->entry = this;
@ -120,7 +124,9 @@ class account_t
: parent(_parent), name(_name), note(_note),
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {}
#ifdef DO_CLEANUP
~account_t();
#endif
std::string fullname() const;
@ -163,13 +169,22 @@ class journal_t
account_t * master;
entries_list entries;
strings_list sources;
#ifdef DO_CLEANUP
char * item_pool;
char * item_pool_end;
#endif
mutable accounts_map accounts_cache;
journal_t() {
master = new account_t(NULL, "");
#ifdef DO_CLEANUP
item_pool = NULL;
#endif
}
#ifdef DO_CLEANUP
~journal_t();
#endif
void add_account(account_t * acct) {
master->add_account(acct);