change to binary loading that increases speed by another 20%
This commit is contained in:
parent
1091f0d07b
commit
b85a536be7
4 changed files with 107 additions and 24 deletions
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
|
|
||||||
account_t::~account_t()
|
account_t::~account_t()
|
||||||
{
|
{
|
||||||
DEBUG_PRINT("ledger.memory.ctors", "dtor account_t");
|
DEBUG_PRINT("ledger.memory.ctors", "dtor account_t");
|
||||||
|
|
@ -16,6 +18,8 @@ account_t::~account_t()
|
||||||
delete (*i).second;
|
delete (*i).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // DO_CLEANUP
|
||||||
|
|
||||||
account_t * account_t::find_account(const std::string& name,
|
account_t * account_t::find_account(const std::string& name,
|
||||||
const bool auto_create)
|
const bool auto_create)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
103
binary.cc
103
binary.cc
|
|
@ -9,7 +9,7 @@
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
const unsigned long binary_magic_number = 0xFFEED765;
|
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
|
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);
|
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)
|
inline std::string read_binary_string(std::istream& in)
|
||||||
{
|
{
|
||||||
std::string temp;
|
std::string temp;
|
||||||
|
|
@ -82,7 +109,7 @@ inline std::string read_binary_string(std::istream& in)
|
||||||
return temp;
|
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;
|
commodity_t::ident_t ident;
|
||||||
read_binary_number(in, ident);
|
read_binary_number(in, ident);
|
||||||
|
|
@ -94,44 +121,46 @@ void read_binary_amount(std::istream& in, amount_t& amt)
|
||||||
amt.read_quantity(in);
|
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 = accounts[read_binary_number<account_t::ident_t>(in) - 1];
|
||||||
xact->account->add_transaction(xact);
|
xact->account->add_transaction(xact);
|
||||||
|
|
||||||
|
new ((amount_t *) &xact->amount) amount_t;
|
||||||
read_binary_amount(in, xact->amount);
|
read_binary_amount(in, xact->amount);
|
||||||
|
|
||||||
if (read_binary_number<char>(in) == 1) {
|
if (read_binary_number<char>(in) == 1) {
|
||||||
xact->cost = new amount_t;
|
xact->cost = new amount_t;
|
||||||
read_binary_amount(in, *xact->cost);
|
read_binary_amount(in, *xact->cost);
|
||||||
|
} else {
|
||||||
|
xact->cost = NULL;
|
||||||
}
|
}
|
||||||
read_binary_number(in, xact->flags);
|
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->date);
|
||||||
read_binary_number(in, entry->state);
|
read_binary_number(in, entry->state);
|
||||||
read_binary_string(in, entry->code);
|
init_binary_string(in, &entry->code);
|
||||||
read_binary_string(in, entry->payee);
|
init_binary_string(in, &entry->payee);
|
||||||
|
|
||||||
|
new(&entry->transactions) transactions_list;
|
||||||
|
|
||||||
for (unsigned long i = 0, count = read_binary_number<unsigned long>(in);
|
for (unsigned long i = 0, count = read_binary_number<unsigned long>(in);
|
||||||
i < count;
|
i < count;
|
||||||
i++) {
|
i++) {
|
||||||
transaction_t * xact = read_binary_transaction(in, entry);
|
read_binary_transaction(in, xact_pool);
|
||||||
entry->add_transaction(xact);
|
xact_pool->entry = entry;
|
||||||
|
entry->transactions.push_back(xact_pool++);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
inline commodity_t * read_binary_commodity(std::istream& in)
|
||||||
}
|
|
||||||
|
|
||||||
commodity_t * read_binary_commodity(std::istream& in)
|
|
||||||
{
|
{
|
||||||
commodity_t * commodity = new commodity_t;
|
commodity_t * commodity = new commodity_t;
|
||||||
commodities.push_back(commodity);
|
commodities.push_back(commodity);
|
||||||
|
|
@ -161,6 +190,7 @@ commodity_t * read_binary_commodity(std::istream& in)
|
||||||
return commodity;
|
return commodity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
account_t * read_binary_account(std::istream& in, account_t * master = NULL)
|
account_t * read_binary_account(std::istream& in, account_t * master = NULL)
|
||||||
{
|
{
|
||||||
account_t * acct = new account_t(NULL);
|
account_t * acct = new account_t(NULL);
|
||||||
|
|
@ -246,17 +276,34 @@ unsigned int read_binary_journal(std::istream& in,
|
||||||
assert(result.second || master);
|
assert(result.second || master);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int count = read_binary_number<unsigned long>(in);
|
unsigned long count = read_binary_number<unsigned long>(in);
|
||||||
for (unsigned long i = 0;
|
unsigned long xact_count = read_binary_number<unsigned long>(in);
|
||||||
i < count;
|
|
||||||
i++) {
|
// Memory needed for the entries and transactions is allocated in
|
||||||
entry_t * entry = read_binary_entry(in, journal);
|
// one large block, which is then chopped up and custom constructed
|
||||||
journal->entries.push_back(entry);
|
// 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();
|
accounts.clear();
|
||||||
commodities.clear();
|
commodities.clear();
|
||||||
bigints.clear();
|
bigints.clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
@ -414,7 +461,15 @@ void write_binary_journal(std::ostream& out, journal_t * journal,
|
||||||
if (! (*i).first.empty())
|
if (! (*i).first.empty())
|
||||||
write_binary_commodity(out, (*i).second);
|
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, journal->entries.size());
|
||||||
|
write_binary_number<unsigned long>(out, xact_count);
|
||||||
|
|
||||||
for (entries_list::const_iterator i = journal->entries.begin();
|
for (entries_list::const_iterator i = journal->entries.begin();
|
||||||
i != journal->entries.end();
|
i != journal->entries.end();
|
||||||
i++)
|
i++)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ namespace ledger {
|
||||||
|
|
||||||
const std::string version = "2.0b";
|
const std::string version = "2.0b";
|
||||||
|
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
|
|
||||||
journal_t::~journal_t()
|
journal_t::~journal_t()
|
||||||
{
|
{
|
||||||
DEBUG_PRINT("ledger.memory.dtors", "dtor 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();
|
for (entries_list::iterator i = entries.begin();
|
||||||
i != entries.end();
|
i != entries.end();
|
||||||
i++)
|
i++)
|
||||||
|
if (! item_pool ||
|
||||||
|
((char *) *i) < item_pool || ((char *) *i) >= item_pool_end)
|
||||||
delete *i;
|
delete *i;
|
||||||
|
|
||||||
|
if (item_pool)
|
||||||
|
delete[] item_pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // DO_CLEANUP
|
||||||
|
|
||||||
bool journal_t::add_entry(entry_t * entry)
|
bool journal_t::add_entry(entry_t * entry)
|
||||||
{
|
{
|
||||||
entries.push_back(entry);
|
entries.push_back(entry);
|
||||||
|
|
|
||||||
15
ledger.h
15
ledger.h
|
|
@ -54,11 +54,13 @@ class transaction_t
|
||||||
cost(NULL), flags(_flags), note(_note), data(NULL) {
|
cost(NULL), flags(_flags), note(_note), data(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
~transaction_t() {
|
~transaction_t() {
|
||||||
//assert(! data);
|
//assert(! data);
|
||||||
if (cost)
|
if (cost)
|
||||||
delete cost;
|
delete cost;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -78,12 +80,14 @@ class entry_t
|
||||||
transactions_list transactions;
|
transactions_list transactions;
|
||||||
|
|
||||||
entry_t() : date(-1), state(UNCLEARED) {}
|
entry_t() : date(-1), state(UNCLEARED) {}
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
~entry_t() {
|
~entry_t() {
|
||||||
for (transactions_list::iterator i = transactions.begin();
|
for (transactions_list::iterator i = transactions.begin();
|
||||||
i != transactions.end();
|
i != transactions.end();
|
||||||
i++)
|
i++)
|
||||||
delete *i;
|
delete *i;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void add_transaction(transaction_t * xact) {
|
void add_transaction(transaction_t * xact) {
|
||||||
xact->entry = this;
|
xact->entry = this;
|
||||||
|
|
@ -120,7 +124,9 @@ class account_t
|
||||||
: parent(_parent), name(_name), note(_note),
|
: parent(_parent), name(_name), note(_note),
|
||||||
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {}
|
depth(parent ? parent->depth + 1 : 0), data(NULL), ident(0) {}
|
||||||
|
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
~account_t();
|
~account_t();
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string fullname() const;
|
std::string fullname() const;
|
||||||
|
|
||||||
|
|
@ -163,13 +169,22 @@ class journal_t
|
||||||
account_t * master;
|
account_t * master;
|
||||||
entries_list entries;
|
entries_list entries;
|
||||||
strings_list sources;
|
strings_list sources;
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
|
char * item_pool;
|
||||||
|
char * item_pool_end;
|
||||||
|
#endif
|
||||||
|
|
||||||
mutable accounts_map accounts_cache;
|
mutable accounts_map accounts_cache;
|
||||||
|
|
||||||
journal_t() {
|
journal_t() {
|
||||||
master = new account_t(NULL, "");
|
master = new account_t(NULL, "");
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
|
item_pool = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef DO_CLEANUP
|
||||||
~journal_t();
|
~journal_t();
|
||||||
|
#endif
|
||||||
|
|
||||||
void add_account(account_t * acct) {
|
void add_account(account_t * acct) {
|
||||||
master->add_account(acct);
|
master->add_account(acct);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue