summaryrefslogtreecommitdiff
path: root/library/binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/binary.cpp')
-rw-r--r--library/binary.cpp112
1 files changed, 101 insertions, 11 deletions
diff --git a/library/binary.cpp b/library/binary.cpp
index 409b024a..8b8fd2ec 100644
--- a/library/binary.cpp
+++ b/library/binary.cpp
@@ -5,32 +5,122 @@
// **************************************************************************
//
#include "binary.h"
-#include <boost/scoped_array.hpp>
#include "../shared/fileIO.h"
+#include <vector>
+#include <wx/stopwatch.h>
-bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback& callback)
+inline
+void setMinSize(std::vector<char>& buffer, size_t minSize)
+{
+ if (buffer.size() < minSize) //this is similar to reserve(), but be need a "properly initialized" array here
+ buffer.resize(minSize);
+}
+
+
+namespace
{
- const size_t BUFFER_SIZE = 512 * 1024; //512 kb seems to be the perfect buffer size
- static boost::scoped_array<unsigned char> memory1(new unsigned char[BUFFER_SIZE]);
- static boost::scoped_array<unsigned char> memory2(new unsigned char[BUFFER_SIZE]);
+class BufferSize
+{
+public:
+ BufferSize() : bufSize(BUFFER_SIZE_START) {}
+
+ void inc()
+ {
+ if (bufSize < BUFFER_SIZE_MAX)
+ bufSize *= 2;
+ }
+
+ void dec()
+ {
+ if (bufSize > BUFFER_SIZE_MIN)
+ bufSize /= 2;
+ }
+
+ operator size_t() const
+ {
+ return bufSize;
+ }
+
+private:
+ static const size_t BUFFER_SIZE_MIN = 128 * 1024;
+ static const size_t BUFFER_SIZE_START = 512 * 1024; //512 kb seems to be a reasonable initial buffer size
+ static const size_t BUFFER_SIZE_MAX = 16 * 1024 * 1024;
+
+ /*Tests on Win7 x64 show that buffer size does NOT matter if files are located on different physical disks!
+ Impact of buffer size when files are on same disk:
+
+ buffer MB/s
+ ------------
+ 64 10
+ 128 19
+ 512 40
+ 1024 48
+ 2048 56
+ 4096 56
+ 8192 56
+ */
+ size_t bufSize;
+};
+}
+
+
+bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback& callback)
+{
FileInput file1(filename1); //throw FileError()
FileInput file2(filename2); //throw FileError()
+ BufferSize bufferSize;
+
+ static std::vector<char> memory1;
+ static std::vector<char> memory2;
+
wxLongLong bytesCompared;
+
+ wxLongLong lastDelayViolation = wxGetLocalTimeMillis();
+
do
{
- const size_t length1 = file1.read(memory1.get(), BUFFER_SIZE); //returns actual number of bytes read; throw FileError()
- const size_t length2 = file2.read(memory2.get(), BUFFER_SIZE); //
+ setMinSize(memory1, bufferSize);
+ setMinSize(memory2, bufferSize);
- if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0)
+ const wxLongLong startTime = wxGetLocalTimeMillis();
+
+ const size_t length1 = file1.read(&memory1[0], bufferSize); //returns actual number of bytes read; throw FileError()
+ const size_t length2 = file2.read(&memory2[0], bufferSize); //
+
+ const wxLongLong stopTime = wxGetLocalTimeMillis();
+
+ //-------- dynamically set buffer size to keep callback interval between 200 - 500ms ---------------------
+ const wxLongLong loopTime = stopTime - startTime;
+ if (loopTime < 200 && stopTime - lastDelayViolation > 2000) //avoid "flipping back": e.g. DVD-Roms read 32MB at once, so first read may be > 300 ms, but second one will be 0ms!
+ {
+ lastDelayViolation = stopTime;
+ bufferSize.inc(); //practically no costs!
+ }
+ else if (loopTime > 500)
+ {
+ lastDelayViolation = stopTime;
+ bufferSize.dec(); //
+ }
+ //------------------------------------------------------------------------------------------------
+
+//#warning
+// static wxLongLong blorg = wxGetLocalTimeMillis();
+// if (wxGetLocalTimeMillis() - blorg > 5000)
+// {
+// blorg = wxGetLocalTimeMillis();
+// wxMessageBox(numberToZstring<size_t>(bufferSize).c_str());
+// }
+
+
+
+ if (length1 != length2 || ::memcmp(&memory1[0], &memory2[0], length1) != 0)
return false;
bytesCompared += length1 * 2;
-
- //send progress updates
- callback.updateCompareStatus(bytesCompared);
+ callback.updateCompareStatus(bytesCompared); //send progress updates
}
while (!file1.eof());
bgstack15