pstats: optimize method that searches for frame at given time

This method is called a lot in the strip chart code and the current implementation can be very slow with a large frame rate
This commit is contained in:
rdb 2024-03-15 11:26:44 +01:00
parent 9fd9e2868e
commit 07902429b8

View File

@ -136,10 +136,11 @@ get_frame_at_time(double time) const {
/**
* Returns the frame number of the latest frame not later than the indicated
* time.
* time. If no frames were found, returns get_oldest_frame_number() - 1.
*
* If the hint is nonnegative, it represents a frame number that we believe
* the correct answer to be near, which may speed the search for the frame.
* If the hint is nonnegative, it represents a frame number (for which
* has_frame() must return true) we believe the correct answer to be after and
* close by, which may speed the search for the frame.
*/
int PStatThreadData::
get_frame_number_at_time(double time, int hint) const {
@ -161,18 +162,66 @@ get_frame_number_at_time(double time, int hint) const {
}
}
// The hint is totally wrong. Start from the end and work backwards.
int i = _frames.size() - 1;
while (i >= 0) {
const PStatFrameData *frame = _frames[i];
if (frame != nullptr && frame->get_start() <= time) {
break;
}
--i;
// The hint is wrong, we have to search the entire set.
int first_i = 0;
int last_i = _frames.size() - 1;
while (first_i < last_i && _frames[first_i] == nullptr) {
++first_i;
}
while (first_i < last_i && _frames[last_i] == nullptr) {
--last_i;
}
return _first_frame_number + i;
if (first_i >= last_i) {
// There are no frames.
return _first_frame_number - 1;
}
// Take a guess by interpolating based on the first and last frame times.
double first = _frames[first_i]->get_start();
if (time < first) {
return _first_frame_number - 1;
}
double last = _frames[last_i]->get_start();
double t = (time - first) / (last - first);
hint = std::max(0, (int)(t * (last_i - first_i))) + first_i;
// Find a frame around the guess that has data.
if (_frames[hint] == nullptr) {
if (hint <= first_i) {
hint = first_i;
}
else do {
// Skip backward until we find a frame with data.
--hint;
} while (_frames[hint] == nullptr);
}
if (_frames[hint]->get_start() <= time) {
// Search forward.
for (int i = hint + 1; i < (int)_frames.size(); ++i) {
const PStatFrameData *frame = _frames[i];
if (frame != nullptr) {
if (frame->get_start() <= time) {
hint = i;
} else {
break;
}
}
}
return _first_frame_number + hint;
}
// Search backward.
for (int i = hint - 1; i >= 0; --i) {
const PStatFrameData *frame = _frames[i];
if (frame != nullptr && frame->get_start() <= time) {
return _first_frame_number + i;
}
}
return _first_frame_number - 1;
}
/**