haikuwebkit/PerformanceTests/MediaTime/main.cpp

95 lines
3.5 KiB
C++
Raw Permalink Normal View History

Playback stalls when a SourceBuffer append causes frame eviction https://bugs.webkit.org/show_bug.cgi?id=167834 Reviewed by Eric Carlson. PerformanceTests: Add an in-page performance test measuring the amount of time required to append a large amount of media data to a SourceBuffer, and then to completely remove that data 30s at a time. Add a microbenchmark for MediaTime which measures the amount of time required to create a 1M entry std::map and traverse the map 1M times. * Media/MSERemoveCodedFrames.html: Added. * Media/media-source-loader.js: (MediaSourceLoader.prototype.get duration): * MediaTime/Configurations/Base.xcconfig: Added. * MediaTime/Configurations/DebugRelease.xcconfig: Added. * MediaTime/Makefile: Added. * MediaTime/MediaTime.xcodeproj/project.pbxproj: Added. * MediaTime/main.cpp: Added. (performTest): (test): (main): * Skipped: Source/WebCore: Test: PerformanceTests/Media/MSERemoveCodedFrames.html Optimize searching through SampleMap by presentationTime. Many of the methods exposed by PresentationOrderSampleMap used the bare std::equal_range, lower_bound, or upper_bound methods. Unlike those methods exposed on std::map, the bare search methods perform a linear O(n) search, rather than a the binary O(log(n)) search used by std::map. Rewrite those methods using the bare methods in terms of the std::map search methods. Drive-by fix: rename findSampleOnOrAfterPresentationTime to findSampleStartingOnOrAfterPresentationTime to make the behavior of the method more explicit. * Modules/mediasource/SampleMap.cpp: (WebCore::PresentationOrderSampleMap::findSampleContainingPresentationTime): (WebCore::PresentationOrderSampleMap::findSampleStartingOnOrAfterPresentationTime): (WebCore::PresentationOrderSampleMap::reverseFindSampleBeforePresentationTime): (WebCore::DecodeOrderSampleMap::findSyncSampleAfterPresentationTime): (WebCore::PresentationOrderSampleMap::findSamplesBetweenPresentationTimes): (WebCore::PresentationOrderSampleMap::findSamplesWithinPresentationRange): (WebCore::PresentationOrderSampleMap::findSampleOnOrAfterPresentationTime): Deleted. * Modules/mediasource/SampleMap.h: (WebCore::PresentationOrderSampleMap::begin): (WebCore::PresentationOrderSampleMap::end): (WebCore::PresentationOrderSampleMap::rbegin): (WebCore::PresentationOrderSampleMap::rend): (WebCore::DecodeOrderSampleMap::begin): (WebCore::DecodeOrderSampleMap::end): (WebCore::DecodeOrderSampleMap::rbegin): (WebCore::DecodeOrderSampleMap::rend): (WebCore::SampleMap::SampleMap): (WebCore::SampleMap::sizeInBytes): (WebCore::SampleMap::decodeOrder): (WebCore::SampleMap::presentationOrder): * Modules/mediasource/SourceBuffer.cpp: (WebCore::removeSamplesFromTrackBuffer): (WebCore::SourceBuffer::removeCodedFrames): (WebCore::SourceBuffer::reenqueueMediaForTime): * WebCore.xcodeproj/project.pbxproj: Source/WTF: Optimize the MediaTime class; specifically the compare() method. The class only needs 6 bits to store the TimeFlags, so make that a uint8_t rather than uint32_t. The implementation is slightly simpler if the TimeScale is unsigned, so make that a uint32_t rather than int32_t. Inline the comparison operators. Optimize the equality comparison by bitwise-and'ing the flags together and masking the result. Optimize for common comparison scenarios (equal timeScales, equal timeValues(), etc.). Attempt the mathematically simpler simpler method for comparing ratios, and only fall back to the complex method if the results of multiplying the timeScale by the timeValue overflows. * wtf/MediaTime.cpp: (WTF::greatestCommonDivisor): (WTF::leastCommonMultiple): (WTF::signum): (WTF::MediaTime::MediaTime): (WTF::MediaTime::createWithFloat): (WTF::MediaTime::createWithDouble): (WTF::MediaTime::operator+): (WTF::MediaTime::operator-): (WTF::MediaTime::operator!): (WTF::MediaTime::operator bool): (WTF::MediaTime::compare): (WTF::MediaTime::setTimeScale): (WTF::abs): (WTF::MediaTime::operator<): Deleted. (WTF::MediaTime::operator>): Deleted. (WTF::MediaTime::operator!=): Deleted. (WTF::MediaTime::operator==): Deleted. (WTF::MediaTime::operator>=): Deleted. (WTF::MediaTime::operator<=): Deleted. * wtf/MediaTime.h: Tools: Add new correctness tests for the Webcore::SampleMap class. Add additional subtests for the WTF::MediaTime class. * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * TestWebKitAPI/Tests/WTF/MediaTime.cpp: (TestWebKitAPI::TEST): * TestWebKitAPI/Tests/WebCore/SampleMap.cpp: Added. (WTF::operator<<): (TestWebKitAPI::TestSample::create): (TestWebKitAPI::TestSample::TestSample): (TestWebKitAPI::TEST_F): Canonical link: https://commits.webkit.org/184921@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@211746 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-06 21:49:24 +00:00
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <chrono>
#include <random>
#include <set>
#include <wtf/MediaTime.h>
using namespace std;
using namespace std::chrono;
static const size_t setSize = 100000;
void performTest(const char* name, function<void()> test)
{
vector<double> runtimes(21);
for (auto& runtime : runtimes) {
auto start = steady_clock::now();
test();
runtime = duration_cast<milliseconds>(steady_clock::now() - start).count();
}
sort(runtimes.begin(), runtimes.end());
double sum = std::accumulate(runtimes.begin(), runtimes.end(), 0);
double mean = sum / runtimes.size();
double median = runtimes[(runtimes.size() + 1) / 2];
double min = runtimes.front();
double max = runtimes.back();
double sqSum = std::inner_product(runtimes.begin(), runtimes.end(), runtimes.begin(), 0);
double stdev = std::sqrt(sqSum / runtimes.size() - mean * mean);
printf("RESULT %s: Time= %g ms", name, sum);
printf("median= %g ms, stdev= %g ms, min= %g ms, max = %g ms", median, stdev, min, max);
}
void test(int32_t count, function<MediaTime(int32_t)> generator)
{
set<MediaTime> times;
for (int32_t i = 0; i < count; ++i)
times.insert(generator(i));
for (int32_t i = 0; i < count; ++i)
times.upper_bound(generator(i));
}
int main(int argc, const char * argv[])
{
performTest("Equal TimeScales", [] { test(setSize, [] (int32_t i) { return MediaTime(i, 1); }); });
performTest("Equal TimeValues", [] { test(setSize, [] (int32_t i) { return MediaTime(1, i + 1); }); });
performTest("Disparate TimeValues & TimeScales", [] { test(setSize, [] (int32_t i) { return MediaTime(i, i + 1); }); });
performTest("Non-uniform", [] {
test(setSize, [] (int32_t i) {
switch (i % 6) {
case 0:
return MediaTime::invalidTime();
case 1:
return MediaTime::positiveInfiniteTime();
case 2:
return MediaTime::negativeInfiniteTime();
case 3:
return MediaTime::indefiniteTime();
case 4:
return MediaTime(i, 1);
case 5:
default:
return MediaTime(i, i + 1);
}
});
});
return 0;
}