Further improve speed of PipeCapture for non-watched output (#777973)

For large output a lot of time is used copying capturebuf to callerbuf
to provide a Glib::ustring copy of the buffer for the update callback.
However update callbacks are only used when commands are run to apply
operations by FileSystem::execute_command() and their output is
incrementally displayed in the UI.  Whereas update callbacks are never
used when commands are used to query information via
Utils::execute_command().

Stop performing interim copying of capturebuf to callerbuf when there
are no update callbacks registered as it is unnecessary.

Time to read portions of the recorded fsck.fat output via
fat16::set_used_sectors() and intermediate copies aren't required:

                     1 MiB     10 MiB   122 MiB
    old code :   0.074 sec   1.41 sec   210 sec [3:30]
    new code :   0.063 sec   0.56 sec     6.57 sec

Bug 777973 - Segmentation fault on bad disk
This commit is contained in:
Mike Fleetwood 2017-03-18 15:35:07 +00:00 committed by Curtis Gedak
parent 6f49f3049d
commit 25780c611b
2 changed files with 23 additions and 8 deletions

View File

@ -55,6 +55,7 @@ private:
std::string capturebuf; // Captured output as UTF-8 characters
size_t line_start; // Index into bytebuf where current line starts
Glib::ustring & callerbuf; // Reference to caller supplied buffer
bool callerbuf_uptodate; // Has capturebuf changed since last copied to callerbuf?
};
} // namepace GParted

View File

@ -37,6 +37,7 @@ PipeCapture::PipeCapture( int fd, Glib::ustring &buffer ) : fill_offset( 0 ),
{
readbuf = new char[READBUF_SIZE];
callerbuf.clear();
callerbuf_uptodate = true;
// tie fd to string
// make channel
channel = Glib::IOChannel::create_from_fd( fd );
@ -95,10 +96,10 @@ bool PipeCapture::OnReadable( Glib::IOCondition condition )
// is drained the partial current line, is pasted into capturebuf at the offset
// where the last line starts. (Capturebuf stores UTF-8 encoded characters in a
// std::string for constant time access to line_start offset). When readbuf
// is drained capturebuf is copied into callerbuf and signal_update slot fired.
// (Callerbuf stores UTF-8 encoded characters in a Glib::ustring). When EOF is
// encountered capturebuf is copied into callerbuf if required and signal_eof slot
// fired.
// is drained and there are registered update callbacks, capturebuf is copied into
// callerbuf and signal_update slot fired. (Callerbuf stores UTF-8 encoded
// characters in a Glib::ustring). When EOF is encountered capturebuf is copied
// into callerbuf if required and signal_eof slot fired.
//
// Golden rule:
// Use Glib::ustrings as little as possible for large amounts of data!
@ -187,6 +188,7 @@ bool PipeCapture::OnReadable( Glib::IOCondition condition )
capturebuf.resize( line_start );
append_unichar_vector_to_utf8( capturebuf, linevec );
line_start = capturebuf.size();
callerbuf_uptodate = false;
linevec.clear();
cursor = 0;
@ -213,13 +215,20 @@ bool PipeCapture::OnReadable( Glib::IOCondition condition )
}
}
// Paste partial line to capture buffer; copy that to callers buffer; and
// fire any update callbacks.
// Paste partial line to capture buffer.
capturebuf.resize( line_start );
append_unichar_vector_to_utf8( capturebuf, linevec );
callerbuf_uptodate = false;
if ( ! signal_update.empty() )
{
// Performance optimisation, especially for large capture buffers:
// only copy capture buffer to callers buffer and fire update
// callbacks when there are any registered update callbacks.
callerbuf = capturebuf;
callerbuf_uptodate = true;
signal_update.emit();
}
return true;
}
@ -228,6 +237,11 @@ bool PipeCapture::OnReadable( Glib::IOCondition condition )
std::cerr << "Pipe IOChannel read failed" << std::endl;
}
if ( ! callerbuf_uptodate )
{
callerbuf = capturebuf;
callerbuf_uptodate = true;
}
// signal completion
signal_eof.emit();
return false;