big speed optimization

This commit is contained in:
Darren Ranalli 2001-07-06 00:23:02 +00:00
parent 13971d239f
commit cf252b93ab
1 changed files with 101 additions and 1 deletions

View File

@ -23,6 +23,25 @@
#include "patchfile.h"
#include "crypto_utils.h" // MD5 stuff
//#define PROFILE_PATCH_BUILD
#ifdef PROFILE_PATCH_BUILD
#include "clockObject.h"
ClockObject *globalClock = ClockObject::get_global_clock();
#define GET_PROFILE_TIME() globalClock->get_real_time()
#define START_PROFILE(var) double var = GET_PROFILE_TIME()
#define END_PROFILE(startTime, name) \
cout << name << " took " << (GET_PROFILE_TIME() - (startTime)) << " seconds" << endl
#else
#define START_PROFILE(var)
#define END_PROFILE(startTime, name)
#endif
// this actually slows things down...
//#define USE_MD5_FOR_HASHTABLE_INDEX_VALUES
@ -401,7 +420,8 @@ calc_hash(const char *buffer) {
PN_uint16 hash_value = 0;
for(int i = 0; i < (int)_footprint_length; i++) {
// this is probably not such a good hash. to be replaced --> TRIED MD5, was not worth it for the execution-time hit on 800Mhz PC
// this is probably not such a good hash. to be replaced
/// --> TRIED MD5, was not worth it for the execution-time hit on 800Mhz PC
hash_value ^= (*buffer) << (i % 8);
buffer++;
}
@ -440,6 +460,8 @@ build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig,
PN_uint32 i;
START_PROFILE(clearTables);
// clear hash table
for(i = 0; i < _HASHTABLESIZE; i++) {
hash_table[i] = _NULL_VALUE;
@ -450,23 +472,77 @@ build_hash_link_tables(const char *buffer_orig, PN_uint32 length_orig,
link_table[i] = _NULL_VALUE;
}
END_PROFILE(clearTables, "clearing hash and link tables");
if(length_orig < _footprint_length) return;
START_PROFILE(hashingFootprints);
#ifdef PROFILE_PATCH_BUILD
double hashCalc = 0.0;
double linkSearch = 0.0;
#endif
// run through original file and hash each footprint
for(i = 0; i < (length_orig - _footprint_length); i++) {
#ifdef PROFILE_PATCH_BUILD
double t = GET_PROFILE_TIME();
#endif
PN_uint16 hash_value = calc_hash(&buffer_orig[i]);
#ifdef PROFILE_PATCH_BUILD
hashCalc += GET_PROFILE_TIME() - t;
#endif
// we must now store this file index in the hash table
// at the offset of the hash value
// to account for multiple file offsets with identical
// hash values, there is a link table with an entry for
// every footprint in the file. We create linked lists
// of offsets in the link table.
// first, set the value in the link table for the current
// offset to whatever the current list head is (the
// value in the hash table) (note that this only works
// because the hash and link tables both use
// _NULL_VALUE to indicate a null index)
link_table[i] = hash_table[hash_value];
// set the new list head; store the current offset in the
// hash table at the offset of the footprint's hash value
hash_table[hash_value] = i;
/*
if (_NULL_VALUE == hash_table[hash_value]) {
// hash entry is empty, store this offset
hash_table[hash_value] = i;
} else {
// hash entry is taken, go to the link table
PN_uint32 link_offset = hash_table[hash_value];
#ifdef PROFILE_PATCH_BUILD
double t = GET_PROFILE_TIME();
#endif
while (_NULL_VALUE != link_table[link_offset]) {
link_offset = link_table[link_offset];
}
#ifdef PROFILE_PATCH_BUILD
linkSearch += GET_PROFILE_TIME() - t;
#endif
link_table[link_offset] = i;
}
*/
}
#ifdef PROFILE_PATCH_BUILD
cout << "time spent calculating footprint hashes: " << hashCalc << endl;
cout << "time spent traversing the link table: " << linkSearch << endl;
#endif
END_PROFILE(hashingFootprints, "hashing footprints");
}
////////////////////////////////////////////////////////////////////
@ -598,6 +674,10 @@ build(Filename &file_orig, Filename &file_new) {
Filename patch_name;
patch_name.set_binary();
START_PROFILE(overall);
START_PROFILE(readFiles);
// Open the original file for read
ifstream stream_orig;
file_orig.set_binary();
@ -643,15 +723,27 @@ build(Filename &file_orig, Filename &file_new) {
stream_orig.close();
stream_new.close();
END_PROFILE(readFiles, "reading files");
START_PROFILE(allocTables);
// allocate hash/link tables
PN_uint32* hash_table = new PN_uint32[_HASHTABLESIZE];
PN_uint32* link_table = new PN_uint32[length_orig];
END_PROFILE(allocTables, "allocating hash and link tables");
START_PROFILE(buildTables);
// build hash and link tables for original file
build_hash_link_tables(buffer_orig, length_orig, hash_table, link_table);
END_PROFILE(buildTables, "building hash and link tables");
// prepare to write the patch file header
START_PROFILE(writeHeader);
// write the patch file header
_datagram.clear();
_datagram.add_uint32(_magic_number);
@ -669,7 +761,11 @@ build(Filename &file_orig, Filename &file_new) {
string msg = _datagram.get_message();
write_stream.write((char *)msg.data(), msg.length());
END_PROFILE(writeHeader, "writing patch file header");
// run through new file
START_PROFILE(buildPatchfile);
PN_uint32 new_pos = 0;
PN_uint32 ADD_offset = new_pos; // this is the offset for the start of ADD operations
@ -711,10 +807,14 @@ build(Filename &file_orig, Filename &file_new) {
emit_COPY(write_stream, 0, 0);
}
END_PROFILE(buildPatchfile, "building patch file");
// write terminator (null ADD, null COPY)
emit_ADD(write_stream, 0, NULL);
emit_COPY(write_stream, 0, 0);
END_PROFILE(overall, "total patch building operation");
return true;
}