use a string pool in binary files; gains 7% read time
This commit is contained in:
parent
5186be2881
commit
d4e39c488d
1 changed files with 94 additions and 55 deletions
149
binary.cc
149
binary.cc
|
|
@ -9,16 +9,7 @@
|
|||
namespace ledger {
|
||||
|
||||
const unsigned long binary_magic_number = 0xFFEED765;
|
||||
static const unsigned long format_version = 0x00020013;
|
||||
|
||||
bool binary_parser_t::test(std::istream& in) const
|
||||
{
|
||||
unsigned long magic;
|
||||
in.read((char *)&magic, sizeof(magic));
|
||||
in.seekg(0);
|
||||
|
||||
return magic == binary_magic_number;
|
||||
}
|
||||
static const unsigned long format_version = 0x00020014;
|
||||
|
||||
static std::deque<account_t *> accounts;
|
||||
static unsigned int account_index;
|
||||
|
|
@ -75,33 +66,6 @@ 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;
|
||||
|
|
@ -121,7 +85,38 @@ inline void read_binary_amount(std::istream& in, amount_t& amt)
|
|||
amt.read_quantity(in);
|
||||
}
|
||||
|
||||
inline void read_binary_transaction(std::istream& in, transaction_t * xact)
|
||||
inline void init_binary_string(char *& string_pool, std::string * str)
|
||||
{
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
unsigned short guard;
|
||||
guard = *((unsigned short *) string_pool);
|
||||
string_pool += sizeof(unsigned short);
|
||||
assert(guard == 0x3001);
|
||||
#endif
|
||||
|
||||
unsigned char len = *string_pool++;
|
||||
if (len == 0xff) {
|
||||
unsigned short slen = *((unsigned short *) string_pool);
|
||||
new(str) std::string(string_pool + sizeof(unsigned short), slen);
|
||||
string_pool += sizeof(unsigned short) + slen;
|
||||
}
|
||||
else if (len) {
|
||||
new(str) std::string(string_pool, len);
|
||||
string_pool += len;
|
||||
}
|
||||
else {
|
||||
new(str) std::string("");
|
||||
}
|
||||
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
guard = *((unsigned short *) string_pool);
|
||||
string_pool += sizeof(unsigned short);
|
||||
assert(guard == 0x3002);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void read_binary_transaction(std::istream& in, transaction_t * xact,
|
||||
char *& string_pool)
|
||||
{
|
||||
xact->account = accounts[read_binary_number<account_t::ident_t>(in) - 1];
|
||||
xact->account->add_transaction(xact);
|
||||
|
|
@ -136,25 +131,25 @@ inline void read_binary_transaction(std::istream& in, transaction_t * xact)
|
|||
xact->cost = NULL;
|
||||
}
|
||||
read_binary_number(in, xact->flags);
|
||||
init_binary_string(in, &xact->note);
|
||||
init_binary_string(string_pool, &xact->note);
|
||||
|
||||
xact->data = NULL;
|
||||
}
|
||||
|
||||
inline void read_binary_entry(std::istream& in, entry_t * entry,
|
||||
transaction_t *& xact_pool, journal_t * journal)
|
||||
transaction_t *& xact_pool, char *& string_pool)
|
||||
{
|
||||
read_binary_number(in, entry->date);
|
||||
read_binary_number(in, entry->state);
|
||||
init_binary_string(in, &entry->code);
|
||||
init_binary_string(in, &entry->payee);
|
||||
init_binary_string(string_pool, &entry->code);
|
||||
init_binary_string(string_pool, &entry->payee);
|
||||
|
||||
new(&entry->transactions) transactions_list;
|
||||
|
||||
for (unsigned long i = 0, count = read_binary_number<unsigned long>(in);
|
||||
i < count;
|
||||
i++) {
|
||||
read_binary_transaction(in, xact_pool);
|
||||
read_binary_transaction(in, xact_pool, string_pool);
|
||||
xact_pool->entry = entry;
|
||||
entry->transactions.push_back(xact_pool++);
|
||||
}
|
||||
|
|
@ -239,10 +234,6 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
account_index =
|
||||
commodity_index = 0;
|
||||
|
||||
if (read_binary_number<unsigned long>(in) != binary_magic_number ||
|
||||
read_binary_number<unsigned long>(in) != format_version)
|
||||
return 0;
|
||||
|
||||
if (! file.empty()) {
|
||||
for (unsigned short i = 0,
|
||||
count = read_binary_number<unsigned short>(in);
|
||||
|
|
@ -276,13 +267,20 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
assert(result.second || master);
|
||||
}
|
||||
|
||||
unsigned long count = read_binary_number<unsigned long>(in);
|
||||
unsigned long xact_count = read_binary_number<unsigned long>(in);
|
||||
unsigned long string_size = read_binary_number<unsigned long>(in);
|
||||
|
||||
char * string_pool = new char[string_size];
|
||||
char * string_next = string_pool;
|
||||
|
||||
in.read(string_pool, string_size);
|
||||
|
||||
// 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%!
|
||||
|
||||
unsigned long count = read_binary_number<unsigned long>(in);
|
||||
unsigned long xact_count = read_binary_number<unsigned long>(in);
|
||||
|
||||
std::size_t pool_size = (sizeof(entry_t) * count +
|
||||
sizeof(transaction_t) * xact_count);
|
||||
char * item_pool = new char[pool_size];
|
||||
|
|
@ -292,10 +290,12 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
sizeof(entry_t) * count);
|
||||
|
||||
for (unsigned long i = 0; i < count; i++) {
|
||||
read_binary_entry(in, entry_pool, xact_pool, journal);
|
||||
read_binary_entry(in, entry_pool, xact_pool, string_next);
|
||||
journal->entries.push_back(entry_pool++);
|
||||
}
|
||||
|
||||
assert(string_next == string_pool + string_size);
|
||||
|
||||
journal->item_pool = item_pool;
|
||||
journal->item_pool_end = item_pool + pool_size;
|
||||
|
||||
|
|
@ -303,9 +303,21 @@ unsigned int read_binary_journal(std::istream& in,
|
|||
commodities.clear();
|
||||
bigints.clear();
|
||||
|
||||
delete[] string_pool;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool binary_parser_t::test(std::istream& in) const
|
||||
{
|
||||
if (read_binary_number<unsigned long>(in) == binary_magic_number &&
|
||||
read_binary_number<unsigned long>(in) == format_version)
|
||||
return true;
|
||||
|
||||
in.seekg(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int binary_parser_t::parse(std::istream& in,
|
||||
journal_t * journal,
|
||||
account_t * master,
|
||||
|
|
@ -369,15 +381,12 @@ void write_binary_transaction(std::ostream& out, transaction_t * xact)
|
|||
write_binary_number<char>(out, 0);
|
||||
}
|
||||
write_binary_number(out, xact->flags);
|
||||
write_binary_string(out, xact->note);
|
||||
}
|
||||
|
||||
void write_binary_entry(std::ostream& out, entry_t * entry)
|
||||
{
|
||||
write_binary_number(out, entry->date);
|
||||
write_binary_number(out, entry->state);
|
||||
write_binary_string(out, entry->code);
|
||||
write_binary_string(out, entry->payee);
|
||||
|
||||
write_binary_number<unsigned long>(out, entry->transactions.size());
|
||||
for (transactions_list::const_iterator i = entry->transactions.begin();
|
||||
|
|
@ -460,10 +469,40 @@ void write_binary_journal(std::ostream& out, journal_t * journal,
|
|||
write_binary_commodity(out, (*i).second);
|
||||
|
||||
unsigned long xact_count = 0;
|
||||
unsigned long string_size = 0;
|
||||
|
||||
for (entries_list::const_iterator i = journal->entries.begin();
|
||||
i != journal->entries.end();
|
||||
i++)
|
||||
xact_count += (*i)->transactions.size();
|
||||
i++) {
|
||||
string_size += 2 + (*i)->code.length() + (*i)->payee.length();
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
string_size += 4 * sizeof(unsigned short);
|
||||
#endif
|
||||
xact_count += (*i)->transactions.size();
|
||||
|
||||
for (transactions_list::const_iterator j = (*i)->transactions.begin();
|
||||
j != (*i)->transactions.end();
|
||||
j++) {
|
||||
string_size += 1 + (*j)->note.length();
|
||||
#if DEBUG_LEVEL >= ALPHA
|
||||
string_size += 2 * sizeof(unsigned short);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
write_binary_number<unsigned long>(out, string_size);
|
||||
|
||||
for (entries_list::const_iterator i = journal->entries.begin();
|
||||
i != journal->entries.end();
|
||||
i++) {
|
||||
write_binary_string(out, (*i)->code);
|
||||
write_binary_string(out, (*i)->payee);
|
||||
|
||||
for (transactions_list::const_iterator j = (*i)->transactions.begin();
|
||||
j != (*i)->transactions.end();
|
||||
j++)
|
||||
write_binary_string(out, (*j)->note);
|
||||
}
|
||||
|
||||
write_binary_number<unsigned long>(out, journal->entries.size());
|
||||
write_binary_number<unsigned long>(out, xact_count);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue