Improve performance of Matroska writer
Especially when dealing with big files the performance is quite bad. This change speeds it up a little by using an unordered map to find the elements for certain offsets instead of using linear lookup. According to callgrind the modified functions where one with the biggest own cost. The function updateRelativeOffsets() was actually the 2nd costly function just below __memcpy_avx_unaligned_erms. Now TagParser::EbmlElement::internalParse(TagParser::Diagnostics&) is quite high as well as standard IO stream functions.
This commit is contained in:
parent
b39e9dc475
commit
fd4c538180
|
@ -96,11 +96,13 @@ void MatroskaCuePositionUpdater::parse(EbmlElement *cuesElement, Diagnostics &di
|
|||
pos = (cueClusterPositionElement = cueTrackPositionsChild)->readUInteger();
|
||||
cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(pos);
|
||||
m_offsets.emplace(cueTrackPositionsChild, pos);
|
||||
m_cueElementByOriginalOffset.emplace(pos, cueTrackPositionsChild);
|
||||
break;
|
||||
case MatroskaIds::CueCodecState:
|
||||
statePos = cueTrackPositionsChild->readUInteger();
|
||||
cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(statePos);
|
||||
m_offsets.emplace(cueTrackPositionsChild, statePos);
|
||||
m_cueElementByOriginalOffset.emplace(statePos, cueTrackPositionsChild);
|
||||
break;
|
||||
case MatroskaIds::CueReference:
|
||||
cueReferenceElementSize = 0;
|
||||
|
@ -122,6 +124,7 @@ void MatroskaCuePositionUpdater::parse(EbmlElement *cuesElement, Diagnostics &di
|
|||
statePos = cueReferenceChild->readUInteger();
|
||||
cueReferenceElementSize += 2 + EbmlElement::calculateUIntegerLength(statePos);
|
||||
m_offsets.emplace(cueReferenceChild, statePos);
|
||||
m_cueElementByOriginalOffset.emplace(statePos, cueReferenceChild);
|
||||
break;
|
||||
default:
|
||||
diag.emplace_back(DiagLevel::Warning,
|
||||
|
@ -143,6 +146,8 @@ void MatroskaCuePositionUpdater::parse(EbmlElement *cuesElement, Diagnostics &di
|
|||
} else if (cueRelativePositionElement) {
|
||||
cueTrackPositionsElementSize += 2 + EbmlElement::calculateUIntegerLength(relPos);
|
||||
m_relativeOffsets.emplace(piecewise_construct, forward_as_tuple(cueRelativePositionElement), forward_as_tuple(pos, relPos));
|
||||
m_cueRelativePositionElementByOriginalOffsets.emplace(
|
||||
piecewise_construct, forward_as_tuple(pos, relPos), forward_as_tuple(cueRelativePositionElement));
|
||||
}
|
||||
cuePointElementSize
|
||||
+= 1 + EbmlElement::calculateSizeDenotationLength(cueTrackPositionsElementSize) + cueTrackPositionsElementSize;
|
||||
|
@ -173,12 +178,19 @@ bool MatroskaCuePositionUpdater::updateOffsets(std::uint64_t originalOffset, std
|
|||
{
|
||||
auto updated = false;
|
||||
const auto newOffsetLength = static_cast<int>(EbmlElement::calculateUIntegerLength(newOffset));
|
||||
for (auto &offset : m_offsets) {
|
||||
if (offset.second.initialValue() == originalOffset && offset.second.currentValue() != newOffset) {
|
||||
updated = updateSize(offset.first->parent(), newOffsetLength
|
||||
- static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue())))
|
||||
for (auto cueElementRange = m_cueElementByOriginalOffset.equal_range(originalOffset); cueElementRange.first != cueElementRange.second;
|
||||
++cueElementRange.first) {
|
||||
auto *const cueElement = cueElementRange.first->second;
|
||||
const auto offsetIterator = m_offsets.find(cueElement);
|
||||
if (offsetIterator == m_offsets.end()) {
|
||||
continue;
|
||||
}
|
||||
auto &offset = offsetIterator->second;
|
||||
if (offset.currentValue() != newOffset) {
|
||||
updated
|
||||
= updateSize(cueElement->parent(), newOffsetLength - static_cast<int>(EbmlElement::calculateUIntegerLength(offset.currentValue())))
|
||||
|| updated;
|
||||
offset.second.update(newOffset);
|
||||
offset.update(newOffset);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
|
@ -193,13 +205,19 @@ bool MatroskaCuePositionUpdater::updateRelativeOffsets(
|
|||
{
|
||||
auto updated = false;
|
||||
const auto newRelativeOffsetLength = static_cast<int>(EbmlElement::calculateUIntegerLength(newRelativeOffset));
|
||||
for (auto &offset : m_relativeOffsets) {
|
||||
if (offset.second.referenceOffset() == referenceOffset && offset.second.initialValue() == originalRelativeOffset
|
||||
&& offset.second.currentValue() != newRelativeOffset) {
|
||||
updated = updateSize(offset.first->parent(), newRelativeOffsetLength
|
||||
- static_cast<int>(EbmlElement::calculateUIntegerLength(offset.second.currentValue())))
|
||||
for (auto cueElementRange = m_cueRelativePositionElementByOriginalOffsets.equal_range(std::make_pair(referenceOffset, originalRelativeOffset));
|
||||
cueElementRange.first != cueElementRange.second; ++cueElementRange.first) {
|
||||
auto *const cueRelativePositionElement = cueElementRange.first->second;
|
||||
const auto offsetIterator = m_relativeOffsets.find(cueRelativePositionElement);
|
||||
if (offsetIterator == m_relativeOffsets.end()) {
|
||||
continue;
|
||||
}
|
||||
auto &offset = offsetIterator->second;
|
||||
if (offset.currentValue() != newRelativeOffset) {
|
||||
updated = updateSize(cueRelativePositionElement->parent(),
|
||||
newRelativeOffsetLength - static_cast<int>(EbmlElement::calculateUIntegerLength(offset.currentValue())))
|
||||
|| updated;
|
||||
offset.second.update(newRelativeOffset);
|
||||
offset.update(newRelativeOffset);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
|
|
|
@ -75,11 +75,23 @@ public:
|
|||
void clear();
|
||||
|
||||
private:
|
||||
struct PairHash {
|
||||
template <class T1, class T2> inline std::size_t operator()(const std::pair<T1, T2> &pair) const
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
seed ^= std::hash<T1>()(pair.first) + 0x9e3779b9;
|
||||
seed ^= std::hash<T2>()(pair.second) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
bool updateSize(EbmlElement *element, int shift);
|
||||
|
||||
EbmlElement *m_cuesElement;
|
||||
std::unordered_map<EbmlElement *, MatroskaOffsetStates> m_offsets;
|
||||
std::unordered_multimap<std::uint64_t, EbmlElement *> m_cueElementByOriginalOffset;
|
||||
std::unordered_map<EbmlElement *, MatroskaReferenceOffsetPair> m_relativeOffsets;
|
||||
std::unordered_multimap<std::pair<std::uint64_t, std::uint64_t>, EbmlElement *, PairHash> m_cueRelativePositionElementByOriginalOffsets;
|
||||
std::unordered_map<EbmlElement *, std::uint64_t> m_sizes;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue