summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--account.cc4
-rw-r--r--binary.cc101
-rw-r--r--ledger.cc11
-rw-r--r--ledger.h15
4 files changed, 107 insertions, 24 deletions
diff --git a/account.cc b/account.cc
index 267d190a..d11633ef 100644
--- a/account.cc
+++ b/account.cc
@@ -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)
{
diff --git a/binary.cc b/binary.cc
index a1dbea98..c3632ea2 100644
--- a/binary.cc
+++ b/binary.cc
@@ -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++)
diff --git a/ledger.cc b/ledger.cc
index de53b7b2..2b80642c 100644
--- a/ledger.cc
+++ b/ledger.cc
@@ -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);
diff --git a/ledger.h b/ledger.h
index 18ae3492..643ee612 100644
--- a/ledger.h
+++ b/ledger.h
@@ -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);