Changeset 217260 in webkit


Ignore:
Timestamp:
May 22, 2017 5:50:58 PM (7 years ago)
Author:
achristensen@apple.com
Message:

REGRESSION(r215686): O(n2) algorithm in CachedRawResource::addDataBuffer
https://bugs.webkit.org/show_bug.cgi?id=172406
<rdar://32109532>

Reviewed by Brady Eidson.

Source/WebCore:

CachedRawResource::calculateIncrementalDataChunk was calling SharedBuffer::data each time the data
was appended to the SharedBuffer. This causes the data to be copied from two segments to one segment,
which causes the O(n2) behavior I was worried about in r215686. These append/data/append/data calls
used to cause O(1) copies per byte which was amortized because of the exponential growth of the buffer.
After this change, there should be 0 copies per byte here, and instead a O(log(n)) binary search in the
call to std::upper_bound to find the next segment of data with a given starting location in the SharedBuffer.
We need to store the additional information of the offsets of the beginnings of the segments in a
SharedBuffer. This doesn't asymptotically increase our memory usage, but it does allow us to asymptotically
decrease the amount of time it takes to find data at a given offset in a SharedBuffer from O(n) to O(log(n)).

This allows us to complete http://speedtest.xfinity.com and new functionality in SharedBuffer is covered by API tests.

  • loader/TextTrackLoader.cpp:

(WebCore::TextTrackLoader::processNewCueData):

  • loader/cache/CachedRawResource.cpp:

(WebCore::CachedRawResource::calculateIncrementalDataChunk):
(WebCore::CachedRawResource::addDataBuffer):
(WebCore::CachedRawResource::finishLoading):

  • loader/cache/CachedRawResource.h:
  • platform/SharedBuffer.cpp:

(WebCore::SharedBuffer::SharedBuffer):
(WebCore::SharedBuffer::combineIntoOneSegment):
(WebCore::SharedBuffer::data):
(WebCore::SharedBuffer::getSomeData):
(WebCore::SharedBuffer::tryCreateArrayBuffer):
(WebCore::SharedBuffer::append):
(WebCore::SharedBuffer::clear):
(WebCore::SharedBuffer::copy):
(WebCore::SharedBuffer::internallyConsistent):
(WebCore::SharedBuffer::hintMemoryNotNeededSoon):
(WebCore::SharedBufferDataView::SharedBufferDataView):
(WebCore::SharedBufferDataView::size):
(WebCore::SharedBufferDataView::data):

  • platform/SharedBuffer.h:
  • platform/cf/SharedBufferCF.cpp:

(WebCore::SharedBuffer::createCFData):
(WebCore::SharedBuffer::hintMemoryNotNeededSoon):
(WebCore::SharedBuffer::append):

  • platform/cocoa/SharedBufferCocoa.mm:

(WebCore::SharedBuffer::createNSData):
(WebCore::SharedBuffer::createCFData):
(WebCore::SharedBuffer::createNSDataArray):

Source/WebKit2:

  • Platform/IPC/DataReference.cpp:

(IPC::SharedBufferDataReference::encode):

  • WebProcess/Plugins/PluginView.cpp:

(WebKit::PluginView::redeliverManualStream):

Tools:

  • TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp:

(TestWebKitAPI::checkBuffer):
(TestWebKitAPI::TEST_F):

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r217256 r217260  
     12017-05-20  Alex Christensen  <achristensen@webkit.org>
     2
     3        REGRESSION(r215686): O(n^2) algorithm in CachedRawResource::addDataBuffer
     4        https://bugs.webkit.org/show_bug.cgi?id=172406
     5        <rdar://32109532>
     6
     7        Reviewed by Brady Eidson.
     8
     9        CachedRawResource::calculateIncrementalDataChunk was calling SharedBuffer::data each time the data
     10        was appended to the SharedBuffer. This causes the data to be copied from two segments to one segment,
     11        which causes the O(n^2) behavior I was worried about in r215686. These append/data/append/data calls
     12        used to cause O(1) copies per byte which was amortized because of the exponential growth of the buffer.
     13        After this change, there should be 0 copies per byte here, and instead a O(log(n)) binary search in the
     14        call to std::upper_bound to find the next segment of data with a given starting location in the SharedBuffer.
     15        We need to store the additional information of the offsets of the beginnings of the segments in a
     16        SharedBuffer. This doesn't asymptotically increase our memory usage, but it does allow us to asymptotically
     17        decrease the amount of time it takes to find data at a given offset in a SharedBuffer from O(n) to O(log(n)).
     18
     19        This allows us to complete http://speedtest.xfinity.com and new functionality in SharedBuffer is covered by API tests.
     20
     21        * loader/TextTrackLoader.cpp:
     22        (WebCore::TextTrackLoader::processNewCueData):
     23        * loader/cache/CachedRawResource.cpp:
     24        (WebCore::CachedRawResource::calculateIncrementalDataChunk):
     25        (WebCore::CachedRawResource::addDataBuffer):
     26        (WebCore::CachedRawResource::finishLoading):
     27        * loader/cache/CachedRawResource.h:
     28        * platform/SharedBuffer.cpp:
     29        (WebCore::SharedBuffer::SharedBuffer):
     30        (WebCore::SharedBuffer::combineIntoOneSegment):
     31        (WebCore::SharedBuffer::data):
     32        (WebCore::SharedBuffer::getSomeData):
     33        (WebCore::SharedBuffer::tryCreateArrayBuffer):
     34        (WebCore::SharedBuffer::append):
     35        (WebCore::SharedBuffer::clear):
     36        (WebCore::SharedBuffer::copy):
     37        (WebCore::SharedBuffer::internallyConsistent):
     38        (WebCore::SharedBuffer::hintMemoryNotNeededSoon):
     39        (WebCore::SharedBufferDataView::SharedBufferDataView):
     40        (WebCore::SharedBufferDataView::size):
     41        (WebCore::SharedBufferDataView::data):
     42        * platform/SharedBuffer.h:
     43        * platform/cf/SharedBufferCF.cpp:
     44        (WebCore::SharedBuffer::createCFData):
     45        (WebCore::SharedBuffer::hintMemoryNotNeededSoon):
     46        (WebCore::SharedBuffer::append):
     47        * platform/cocoa/SharedBufferCocoa.mm:
     48        (WebCore::SharedBuffer::createNSData):
     49        (WebCore::SharedBuffer::createCFData):
     50        (WebCore::SharedBuffer::createNSDataArray):
     51
    1522017-05-22  Chris Dumez  <cdumez@apple.com>
    253
  • trunk/Source/WebCore/loader/TextTrackLoader.cpp

    r216217 r217260  
    9292        m_cueParser = std::make_unique<WebVTTParser>(static_cast<WebVTTParserClient*>(this), m_scriptExecutionContext);
    9393
    94     auto bytesToSkip = m_parseOffset;
    95     for (const auto& segment : *buffer) {
    96         if (bytesToSkip > segment->size()) {
    97             bytesToSkip -= segment->size();
    98             continue;
    99         }
    100         auto bytesToUse = segment->size() - bytesToSkip;
    101         m_cueParser->parseBytes(segment->data() + bytesToSkip, bytesToUse);
    102         bytesToSkip = 0;
    103         m_parseOffset += bytesToUse;
     94    while (m_parseOffset < buffer->size()) {
     95        auto data = buffer->getSomeData(m_parseOffset);
     96        m_cueParser->parseBytes(data.data(), data.size());
     97        m_parseOffset += data.size();
    10498    }
    10599}
  • trunk/Source/WebCore/loader/cache/CachedRawResource.cpp

    r212449 r217260  
    4545}
    4646
    47 const char* CachedRawResource::calculateIncrementalDataChunk(SharedBuffer* data, unsigned& incrementalDataLength)
    48 {
    49     incrementalDataLength = 0;
    50     if (!data)
    51         return nullptr;
    52 
    53     unsigned previousDataLength = encodedSize();
    54     ASSERT(data->size() >= previousDataLength);
    55     incrementalDataLength = data->size() - previousDataLength;
    56     return data->data() + previousDataLength;
     47std::optional<SharedBufferDataView> CachedRawResource::calculateIncrementalDataChunk(const SharedBuffer* data) const
     48{
     49    size_t previousDataLength = encodedSize();
     50    if (!data || data->size() <= previousDataLength)
     51        return std::nullopt;
     52    return data->getSomeData(previousDataLength);
    5753}
    5854
     
    6359    m_data = &data;
    6460
    65     unsigned incrementalDataLength;
    66     const char* incrementalData = calculateIncrementalDataChunk(&data, incrementalDataLength);
     61    auto incrementalData = calculateIncrementalDataChunk(&data);
    6762    setEncodedSize(data.size());
    68     notifyClientsDataWasReceived(incrementalData, incrementalDataLength);
     63    if (incrementalData)
     64        notifyClientsDataWasReceived(incrementalData->data(), incrementalData->size());
    6965    if (dataBufferingPolicy() == DoNotBufferData) {
    7066        if (m_loader)
     
    9187        m_data = data;
    9288
    93         unsigned incrementalDataLength;
    94         const char* incrementalData = calculateIncrementalDataChunk(data, incrementalDataLength);
    95         if (data)
     89        if (auto incrementalData = calculateIncrementalDataChunk(data)) {
    9690            setEncodedSize(data->size());
    97         notifyClientsDataWasReceived(incrementalData, incrementalDataLength);
     91            notifyClientsDataWasReceived(incrementalData->data(), incrementalData->size());
     92        }
    9893    }
    9994
  • trunk/Source/WebCore/loader/cache/CachedRawResource.h

    r212449 r217260  
    2929class CachedResourceClient;
    3030class ResourceTiming;
     31class SharedBufferDataView;
    3132class SubresourceLoader;
    3233
     
    7071    bool mayTryReplaceEncodedData() const override { return m_allowEncodedDataReplacement; }
    7172
    72     const char* calculateIncrementalDataChunk(SharedBuffer*, unsigned& incrementalDataLength);
     73    std::optional<SharedBufferDataView> calculateIncrementalDataChunk(const SharedBuffer*) const;
    7374    void notifyClientsDataWasReceived(const char* data, unsigned length);
    7475
  • trunk/Source/WebCore/platform/SharedBuffer.cpp

    r215686 r217260  
    5151    : m_size(fileData.size())
    5252{
    53     m_segments.append(DataSegment::create(WTFMove(fileData)));
     53    m_segments.append({0, DataSegment::create(WTFMove(fileData))});
    5454}
    5555
     
    7777void SharedBuffer::combineIntoOneSegment() const
    7878{
     79#if !ASSERT_DISABLED
     80    // FIXME: We ought to be able to set this to true and have no assertions fire.
     81    // Remove all instances of appending after calling this, because they are all O(n^2) algorithms since r215686.
     82    // m_hasBeenCombinedIntoOneSegment = true;
     83#endif
    7984    if (m_segments.size() <= 1)
    8085        return;
     
    8388    combinedData.reserveInitialCapacity(m_size);
    8489    for (const auto& segment : m_segments)
    85         combinedData.append(segment->data(), segment->size());
     90        combinedData.append(segment.segment->data(), segment.segment->size());
    8691    ASSERT(combinedData.size() == m_size);
    8792    m_segments.clear();
    88     m_segments.append(DataSegment::create(WTFMove(combinedData)));
     93    m_segments.append({0, DataSegment::create(WTFMove(combinedData))});
    8994    ASSERT(m_segments.size() == 1);
     95    ASSERT(internallyConsistent());
    9096}
    9197
     
    95101        return nullptr;
    96102    combineIntoOneSegment();
    97     return m_segments[0]->data();
     103    ASSERT(internallyConsistent());
     104    return m_segments[0].segment->data();
     105}
     106
     107SharedBufferDataView SharedBuffer::getSomeData(size_t position) const
     108{
     109    RELEASE_ASSERT(position < m_size);
     110    auto comparator = [](const size_t& position, const DataSegmentVectorEntry& entry) {
     111        return position < entry.beginPosition;
     112    };
     113    const DataSegmentVectorEntry* element = std::upper_bound(m_segments.begin(), m_segments.end(), position, comparator);
     114    element--; // std::upper_bound gives a pointer to the element that is greater than position. We want the element just before that.
     115    return { element->segment.copyRef(), position - element->beginPosition };
    98116}
    99117
     
    108126    size_t position = 0;
    109127    for (const auto& segment : m_segments) {
    110         memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment->data(), segment->size());
    111         position += segment->size();
     128        memcpy(static_cast<char*>(arrayBuffer->data()) + position, segment.segment->data(), segment.segment->size());
     129        position += segment.segment->size();
    112130    }
    113131
    114132    ASSERT(position == m_size);
     133    ASSERT(internallyConsistent());
    115134    return arrayBuffer;
    116135}
     
    118137void SharedBuffer::append(const SharedBuffer& data)
    119138{
    120     m_size += data.m_size;
     139    ASSERT(!m_hasBeenCombinedIntoOneSegment);
    121140    m_segments.reserveCapacity(m_segments.size() + data.m_segments.size());
    122     for (const auto& segment : data.m_segments)
    123         m_segments.uncheckedAppend(segment.copyRef());
     141    for (const auto& element : data.m_segments) {
     142        m_segments.uncheckedAppend({m_size, element.segment.copyRef()});
     143        m_size += element.segment->size();
     144    }
     145    ASSERT(internallyConsistent());
    124146}
    125147
    126148void SharedBuffer::append(const char* data, size_t length)
    127149{
    128     m_size += length;
     150    ASSERT(!m_hasBeenCombinedIntoOneSegment);
    129151    Vector<char> vector;
    130152    vector.append(data, length);
    131     m_segments.append(DataSegment::create(WTFMove(vector)));
     153    m_segments.append({m_size, DataSegment::create(WTFMove(vector))});
     154    m_size += length;
     155    ASSERT(internallyConsistent());
    132156}
    133157
    134158void SharedBuffer::append(Vector<char>&& data)
    135159{
    136     m_size += data.size();
    137     m_segments.append(DataSegment::create(WTFMove(data)));
     160    ASSERT(!m_hasBeenCombinedIntoOneSegment);
     161    auto dataSize = data.size();
     162    m_segments.append({m_size, DataSegment::create(WTFMove(data))});
     163    m_size += dataSize;
     164    ASSERT(internallyConsistent());
    138165}
    139166
     
    142169    m_size = 0;
    143170    m_segments.clear();
     171    ASSERT(internallyConsistent());
    144172}
    145173
     
    149177    clone->m_size = m_size;
    150178    clone->m_segments.reserveInitialCapacity(m_segments.size());
    151     for (const auto& segment : m_segments)
    152         clone->m_segments.uncheckedAppend(segment.copyRef());
     179    for (const auto& element : m_segments)
     180        clone->m_segments.uncheckedAppend({element.beginPosition, element.segment.copyRef()});
     181    ASSERT(clone->internallyConsistent());
     182    ASSERT(internallyConsistent());
    153183    return clone;
    154184}
     185
     186#if !ASSERT_DISABLED
     187bool SharedBuffer::internallyConsistent() const
     188{
     189    size_t position = 0;
     190    for (const auto& element : m_segments) {
     191        if (element.beginPosition != position)
     192            return false;
     193        position += element.segment->size();
     194    }
     195    return position == m_size;
     196}
     197#endif
    155198
    156199const char* SharedBuffer::DataSegment::data() const
     
    170213
    171214#if !USE(CF)
    172 void SharedBuffer::hintMemoryNotNeededSoon()
     215void SharedBuffer::hintMemoryNotNeededSoon() const
    173216{
    174217}
     
    188231    );
    189232    return WTF::visit(visitor, m_immutableData);
     233}
     234
     235SharedBufferDataView::SharedBufferDataView(Ref<SharedBuffer::DataSegment>&& segment, size_t positionWithinSegment)
     236    : m_positionWithinSegment(positionWithinSegment)
     237    , m_segment(WTFMove(segment))
     238{
     239    ASSERT(positionWithinSegment < m_segment->size());
     240}
     241
     242size_t SharedBufferDataView::size() const
     243{
     244    return m_segment->size() - m_positionWithinSegment;
     245}
     246
     247const char* SharedBufferDataView::data() const
     248{
     249    return m_segment->data() + m_positionWithinSegment;
    190250}
    191251
  • trunk/Source/WebCore/platform/SharedBuffer.h

    r215686 r217260  
    5050
    5151namespace WebCore {
    52    
     52
     53class SharedBufferDataView;
     54
    5355class WEBCORE_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
    5456public:
     
    6163   
    6264#if USE(FOUNDATION)
    63     RetainPtr<NSData> createNSData();
     65    RetainPtr<NSData> createNSData() const;
    6466    RetainPtr<NSArray> createNSDataArray() const;
    6567    static Ref<SharedBuffer> create(NSData *);
    6668#endif
    6769#if USE(CF)
    68     RetainPtr<CFDataRef> createCFData();
     70    RetainPtr<CFDataRef> createCFData() const;
    6971    static Ref<SharedBuffer> create(CFDataRef);
    7072    void append(CFDataRef);
     
    139141    };
    140142
    141     using DataSegmentVector = Vector<Ref<DataSegment>, 1>;
     143    struct DataSegmentVectorEntry {
     144        size_t beginPosition;
     145        Ref<DataSegment> segment;
     146    };
     147    using DataSegmentVector = Vector<DataSegmentVectorEntry, 1>;
    142148    DataSegmentVector::const_iterator begin() const { return m_segments.begin(); }
    143149    DataSegmentVector::const_iterator end() const { return m_segments.end(); }
     150   
     151    // begin and end take O(1) time, this takes O(log(N)) time.
     152    SharedBufferDataView getSomeData(size_t position) const;
    144153
    145     void hintMemoryNotNeededSoon();
     154    void hintMemoryNotNeededSoon() const;
    146155
    147156private:
     
    164173    size_t m_size { 0 };
    165174    mutable DataSegmentVector m_segments;
     175
     176#if !ASSERT_DISABLED
     177    mutable bool m_hasBeenCombinedIntoOneSegment { false };
     178    bool internallyConsistent() const;
     179#endif
     180};
     181
     182class WEBCORE_EXPORT SharedBufferDataView {
     183public:
     184    SharedBufferDataView(Ref<SharedBuffer::DataSegment>&&, size_t);
     185    size_t size() const;
     186    const char* data() const;
     187private:
     188    size_t m_positionWithinSegment;
     189    Ref<SharedBuffer::DataSegment> m_segment;
    166190};
    167191
  • trunk/Source/WebCore/platform/cf/SharedBufferCF.cpp

    r215845 r217260  
    4242// so only use this version for non-Foundation.
    4343#if !USE(FOUNDATION)
    44 RetainPtr<CFDataRef> SharedBuffer::createCFData()
     44RetainPtr<CFDataRef> SharedBuffer::createCFData() const
    4545{
    4646    if (m_segments.size() == 1) {
    47         if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(m_segments[0]->m_immutableData))
     47        if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(m_segments[0].segment->m_immutableData))
    4848            return *data;
    4949    }
     
    5757}
    5858
    59 void SharedBuffer::hintMemoryNotNeededSoon()
     59void SharedBuffer::hintMemoryNotNeededSoon() const
    6060{
    61     for (const auto& segment : m_segments) {
    62         if (segment->hasOneRef()) {
    63             if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(segment->m_immutableData))
     61    for (const auto& entry : m_segments) {
     62        if (entry.segment->hasOneRef()) {
     63            if (auto data = WTF::get_if<RetainPtr<CFDataRef>>(entry.segment->m_immutableData))
    6464                OSAllocator::hintMemoryNotNeededSoon(const_cast<UInt8*>(CFDataGetBytePtr(data->get())), CFDataGetLength(data->get()));
    6565        }
     
    6969void SharedBuffer::append(CFDataRef data)
    7070{
     71    ASSERT(!m_hasBeenCombinedIntoOneSegment);
    7172    if (data) {
     73        m_segments.append({m_size, DataSegment::create(data)});
    7274        m_size += CFDataGetLength(data);
    73         m_segments.append(DataSegment::create(data));
    7475    }
     76    ASSERT(internallyConsistent());
    7577}
    7678
  • trunk/Source/WebCore/platform/cocoa/SharedBufferCocoa.mm

    r215686 r217260  
    8989}
    9090
    91 RetainPtr<NSData> SharedBuffer::createNSData()
     91RetainPtr<NSData> SharedBuffer::createNSData() const
    9292{
    9393    return adoptNS((NSData *)createCFData().leakRef());
    9494}
    9595
    96 RetainPtr<CFDataRef> SharedBuffer::createCFData()
     96RetainPtr<CFDataRef> SharedBuffer::createCFData() const
    9797{
    9898    combineIntoOneSegment();
     
    100100        return adoptCF(CFDataCreate(nullptr, nullptr, 0));
    101101    ASSERT(m_segments.size() == 1);
    102     return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:m_segments[0]]).leakRef());
     102    return adoptCF((CFDataRef)adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:m_segments[0].segment]).leakRef());
    103103}
    104104
     
    115115    auto dataArray = adoptNS([[NSMutableArray alloc] initWithCapacity:m_segments.size()]);
    116116    for (const auto& segment : m_segments)
    117         [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:segment]).get()];
     117        [dataArray addObject:adoptNS([[WebCoreSharedBufferData alloc] initWithSharedBufferDataSegment:segment.segment]).get()];
    118118    return WTFMove(dataArray);
    119119}
  • trunk/Source/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp

    r216067 r217260  
    12071207        return;
    12081208
    1209     for (const auto& segment : buffer.get())
    1210         handleDataReceived(segment->data(), segment->size());
     1209    for (const auto& element : buffer.get())
     1210        handleDataReceived(element.segment->data(), element.segment->size());
    12111211}
    12121212
  • trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp

    r217246 r217260  
    4646{
    4747    unsigned bytesExtracted = 0;
    48     for (const auto& segment : sharedBuffer) {
    49         if (bytesExtracted + segment->size() <= bufferLength) {
    50             memcpy(buffer + bytesExtracted, segment->data(), segment->size());
    51             bytesExtracted += segment->size();
     48    for (const auto& element : sharedBuffer) {
     49        if (bytesExtracted + element.segment->size() <= bufferLength) {
     50            memcpy(buffer + bytesExtracted, element.segment->data(), element.segment->size());
     51            bytesExtracted += element.segment->size();
    5252        } else {
    53             ASSERT(bufferLength - bytesExtracted < segment->size());
    54             memcpy(buffer + bytesExtracted, segment->data(), bufferLength - bytesExtracted);
     53            ASSERT(bufferLength - bytesExtracted < element.segment->size());
     54            memcpy(buffer + bytesExtracted, element.segment->data(), bufferLength - bytesExtracted);
    5555            bytesExtracted = bufferLength;
    5656            break;
  • trunk/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp

    r216882 r217260  
    159159
    160160        auto bytesToSkip = m_readOffset;
    161         for (const auto& segment : data) {
    162             if (bytesToSkip > segment->size()) {
    163                 bytesToSkip -= segment->size();
     161       
     162        // FIXME: Use getSomeData which is O(log(n)) instead of skipping bytes which is O(n).
     163        for (const auto& element : data) {
     164            if (bytesToSkip > element.segment->size()) {
     165                bytesToSkip -= element.segment->size();
    164166                continue;
    165167            }
    166             auto bytesToUse = segment->size() - bytesToSkip;
     168            auto bytesToUse = element.segment->size() - bytesToSkip;
    167169            m_readOffset += bytesToUse;
    168170            m_currentBufferSize = m_readOffset;
    169             png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment->data() + bytesToSkip)), bytesToUse);
     171            png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(element.segment->data() + bytesToSkip)), bytesToUse);
    170172            bytesToSkip = 0;
    171173            // We explicitly specify the superclass encodedDataStatus() because we
  • trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp

    r215686 r217260  
    3131    ASSERT(soupBuffer);
    3232    m_size = soupBuffer->length;
    33     m_segments.append(DataSegment::create(GUniquePtr<SoupBuffer>(soupBuffer)));
     33    m_segments.append({0, DataSegment::create(GUniquePtr<SoupBuffer>(soupBuffer))});
    3434}
    3535
  • trunk/Source/WebKit2/ChangeLog

    r217252 r217260  
     12017-05-20  Alex Christensen  <achristensen@webkit.org>
     2
     3        REGRESSION(r215686): O(n^2) algorithm in CachedRawResource::addDataBuffer
     4        https://bugs.webkit.org/show_bug.cgi?id=172406
     5        <rdar://32109532>
     6
     7        Reviewed by Brady Eidson.
     8
     9        * Platform/IPC/DataReference.cpp:
     10        (IPC::SharedBufferDataReference::encode):
     11        * WebProcess/Plugins/PluginView.cpp:
     12        (WebKit::PluginView::redeliverManualStream):
     13
    1142017-05-22  Yongjun Zhang  <yongjun_zhang@apple.com>
    215
  • trunk/Source/WebKit2/Platform/IPC/DataReference.cpp

    r215686 r217260  
    4848    encoder << bufferSize;
    4949
    50     for (const auto& segment : *m_buffer)
    51         encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(segment->data()), segment->size(), 1);
     50    for (const auto& element : *m_buffer)
     51        encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(element.segment->data()), element.segment->size(), 1);
    5252}
    5353
  • trunk/Source/WebKit2/WebProcess/Plugins/PluginView.cpp

    r216541 r217260  
    13121312    // Deliver the data.
    13131313    if (m_manualStreamData) {
    1314         for (const auto& segment : *m_manualStreamData)
    1315             manualLoadDidReceiveData(segment->data(), segment->size());
     1314        for (const auto& element : *m_manualStreamData)
     1315            manualLoadDidReceiveData(element.segment->data(), element.segment->size());
    13161316        m_manualStreamData = nullptr;
    13171317    }
  • trunk/Tools/ChangeLog

    r217259 r217260  
     12017-05-20  Alex Christensen  <achristensen@webkit.org>
     2
     3        REGRESSION(r215686): O(n^2) algorithm in CachedRawResource::addDataBuffer
     4        https://bugs.webkit.org/show_bug.cgi?id=172406
     5        <rdar://32109532>
     6
     7        Reviewed by Brady Eidson.
     8
     9        * TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp:
     10        (TestWebKitAPI::checkBuffer):
     11        (TestWebKitAPI::TEST_F):
     12
    1132017-05-22  Jason Marcell  <jmarcell@apple.com>
    214
  • trunk/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp

    r215686 r217260  
    161161}
    162162
    163 }
     163static void checkBuffer(const char* buffer, size_t bufferLength, const char* expected)
     164{
     165    // expected is null terminated, buffer is not.
     166    size_t length = strlen(expected);
     167    EXPECT_EQ(length, bufferLength);
     168    for (size_t i = 0; i < length; ++i)
     169        EXPECT_EQ(buffer[i], expected[i]);
     170}
     171
     172TEST_F(SharedBufferTest, getSomeData)
     173{
     174    Vector<char> s1 = {'a', 'b', 'c', 'd'};
     175    Vector<char> s2 = {'e', 'f', 'g', 'h'};
     176    Vector<char> s3 = {'i', 'j', 'k', 'l'};
     177   
     178    auto buffer = SharedBuffer::create();
     179    buffer->append(WTFMove(s1));
     180    buffer->append(WTFMove(s2));
     181    buffer->append(WTFMove(s3));
     182   
     183    auto abcd = buffer->getSomeData(0);
     184    auto gh = buffer->getSomeData(6);
     185    auto h = buffer->getSomeData(7);
     186    auto ijkl = buffer->getSomeData(8);
     187    auto kl = buffer->getSomeData(10);
     188    auto abcdefghijkl = buffer->data();
     189    auto ghijkl = buffer->getSomeData(6);
     190    auto l = buffer->getSomeData(11);
     191    checkBuffer(abcd.data(), abcd.size(), "abcd");
     192    checkBuffer(gh.data(), gh.size(), "gh");
     193    checkBuffer(h.data(), h.size(), "h");
     194    checkBuffer(ijkl.data(), ijkl.size(), "ijkl");
     195    checkBuffer(kl.data(), kl.size(), "kl");
     196    checkBuffer(abcdefghijkl, buffer->size(), "abcdefghijkl");
     197    checkBuffer(ghijkl.data(), ghijkl.size(), "ghijkl");
     198    checkBuffer(l.data(), l.size(), "l");
     199}
     200
     201}
Note: See TracChangeset for help on using the changeset viewer.