Changeset 16622 in webkit


Ignore:
Timestamp:
Sep 28, 2006 2:07:39 PM (18 years ago)
Author:
darin
Message:

JavaScriptCore:

Reviewed by Alice.

  • support for change that should fix <rdar://problem/4733044> REGRESSION: XML iBench shows 10% perf. regression (copying strings while decoding)
  • wtf/Vector.h: Changed VectorBuffer so that the general case contains an instance of the 0 case, since deriving from it was violating the Liskov Substitution Principle. (WTF::VectorBuffer::releaseBuffer): Added. Releases the buffer so it can be adopted by another data structure that uses the FastMalloc.h allocator. Returns 0 if the internal buffer was being used. (WTF::Vector::releaseBuffer): Added. Releases the buffer as above or creates a new one in the case where the internal buffer was being used.

WebCore:

Reviewed by Alice.

  • change that should fix <rdar://problem/4733044> REGRESSION: XML iBench shows 10% perf. regression (copying strings while decoding)

Use Vector<UChar> instead of String when building up the decoded string in
the ICU and Mac decoders. Using String leads to O(n2) behavior because
String grows the buffer every single time that append is called. Using
Vector::append instead of String::append also avoids constructing a string
each time just to append and a questionable copy that is done inside the
String::append function which also contributed to the slowness.

  • platform/PlatformString.h:
  • platform/String.cpp: (WebCore::String::adopt): Added. Makes a String from a Vector<UChar>, adopting the buffer from the vector to avoid copying and memory allocation.
  • platform/StringImpl.h:
  • platform/StringImpl.cpp: (WebCore::StringImpl::adopt): Ditto.
  • platform/StreamingTextDecoder.h:
  • platform/StreamingTextDecoder.cpp: (WebCore::TextCodec::appendOmittingBOM): Change to use a Vector<UChar> instead of a String, since vectors have better resizing performance (they store a separate capacity).
  • platform/StreamingTextDecoderICU.cpp: (WebCore::TextCodecICU::decode):
  • platform/mac/StreamingTextDecoderMac.cpp: (WebCore::TextCodecMac::decode): Change to use Vector<UChar> instead of String and then create a string at the end of the process using the new adopt function.
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r16614 r16622  
     12006-09-28  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Alice.
     4
     5        - support for change that should fix <rdar://problem/4733044>
     6          REGRESSION: XML iBench shows 10% perf. regression (copying
     7          strings while decoding)
     8
     9        * wtf/Vector.h: Changed VectorBuffer so that the general case
     10        contains an instance of the 0 case, since deriving from it
     11        was violating the Liskov Substitution Principle.
     12        (WTF::VectorBuffer::releaseBuffer): Added. Releases the buffer so it can
     13        be adopted by another data structure that uses the FastMalloc.h allocator.
     14        Returns 0 if the internal buffer was being used.
     15        (WTF::Vector::releaseBuffer): Added. Releases the buffer as above or creates
     16        a new one in the case where the internal buffer was being used.
     17
    1182006-09-28  Maciej Stachowiak  <mjs@apple.com>
    219
  • trunk/JavaScriptCore/wtf/Vector.h

    r16533 r16622  
    219219
    220220    template<typename T>
    221     class VectorBuffer<T, 0>
    222     {
     221    class VectorBuffer<T, 0> {
    223222    public:
    224223        VectorBuffer()
     224            : m_buffer(0), m_capacity(0)
     225        {
     226        }
     227       
     228        VectorBuffer(size_t capacity)
     229#if !ASSERT_DISABLED
    225230            : m_capacity(0)
    226             , m_buffer(0)
    227         {
    228         }
    229        
    230         VectorBuffer(size_t capacity)
    231             : m_capacity(0)
     231#endif
    232232        {
    233233            allocateBuffer(capacity);
     
    239239        }
    240240       
    241         void deallocateBuffer(T* buffer)
     241        static void deallocateBuffer(T* buffer)
    242242        {
    243243            fastFree(buffer);
     
    250250            if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
    251251                abort();
    252             m_buffer = reinterpret_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
     252            m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T)));
    253253        }
    254254
     
    257257        size_t capacity() const { return m_capacity; }
    258258
     259        T* releaseBuffer()
     260        {
     261            T* buffer = m_buffer;
     262            m_buffer = 0;
     263            m_capacity = 0;
     264            return buffer;
     265        }
     266
    259267    protected:
    260268        VectorBuffer(T* buffer, size_t capacity)
    261             : m_capacity(capacity)
    262             , m_buffer(buffer)
    263         {
    264         }
    265 
     269            : m_buffer(buffer), m_capacity(capacity)
     270        {
     271        }
     272
     273        T* m_buffer;
     274
     275    private:
    266276        size_t m_capacity;
    267         T *m_buffer;
    268     };
    269 
    270     template<typename T, size_t inlineCapacity>
    271     class VectorBuffer : public VectorBuffer<T, 0> {
     277    };
     278
     279    template<typename T, size_t inlineCapacity>
     280    class VectorBuffer : private VectorBuffer<T, 0> {
    272281    private:
    273282        typedef VectorBuffer<T, 0> BaseBuffer;
    274283    public:
    275         VectorBuffer() 
     284        VectorBuffer()
    276285            : BaseBuffer(inlineBuffer(), inlineCapacity)
    277286        {
     
    282291        {
    283292            if (capacity > inlineCapacity)
    284                 BaseBuffer::allocateBuffer(capacity);
     293                allocateBuffer(capacity);
    285294        }
    286295
    287296        ~VectorBuffer()
    288297        {
    289             if (BaseBuffer::buffer() == inlineBuffer())
     298            if (buffer() == inlineBuffer())
    290299                BaseBuffer::m_buffer = 0;
    291300        }
     
    297306        }
    298307
     308        using BaseBuffer::allocateBuffer;
     309
     310        using BaseBuffer::buffer;
     311        using BaseBuffer::capacity;
     312
     313        T* releaseBuffer()
     314        {
     315            if (buffer() == inlineBuffer())
     316                return 0;
     317            return BaseBuffer::releaseBuffer();
     318        }
     319
    299320    private:
    300321        static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
    301         T *inlineBuffer() { return reinterpret_cast<T *>(&m_inlineBuffer); }
     322        T* inlineBuffer() { return reinterpret_cast<T*>(&m_inlineBuffer); }
     323
    302324        char m_inlineBuffer[m_inlineBufferSize];
    303325    };
     
    409431        void fill(const T& val) { fill(val, size()); }
    410432
     433        T* releaseBuffer();
     434
    411435    private:
    412436        void expandCapacity(size_t newMinCapacity);
     
    598622
    599623    template<typename T, size_t inlineCapacity>
     624    T* Vector<T, inlineCapacity>::releaseBuffer()
     625    {
     626        T* buffer = m_impl.releaseBuffer();
     627        if (!buffer && m_size) {
     628            // If the vector had some data, but no buffer to release,
     629            // that means it was using the inline buffer. In that case,
     630            // we create a brand new buffer so the caller always gets one.
     631            size_t bytes = m_size * sizeof(T);
     632            buffer = static_cast<T*>(fastMalloc(bytes));
     633            memcpy(buffer, data(), bytes);
     634        }
     635        m_size = 0;
     636        return buffer;
     637    }
     638
     639    template<typename T, size_t inlineCapacity>
    600640    void deleteAllValues(const Vector<T, inlineCapacity>& collection)
    601641    {
  • trunk/WebCore/ChangeLog

    r16616 r16622  
     12006-09-28  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Alice.
     4
     5        - change that should fix <rdar://problem/4733044> REGRESSION: XML iBench shows
     6          10% perf. regression (copying strings while decoding)
     7
     8        Use Vector<UChar> instead of String when building up the decoded string in
     9        the ICU and Mac decoders. Using String leads to O(n^2) behavior because
     10        String grows the buffer every single time that append is called. Using
     11        Vector::append instead of String::append also avoids constructing a string
     12        each time just to append and a questionable copy that is done inside the
     13        String::append function which also contributed to the slowness.
     14
     15        * platform/PlatformString.h:
     16        * platform/String.cpp: (WebCore::String::adopt): Added. Makes a String from a
     17        Vector<UChar>, adopting the buffer from the vector to avoid copying and memory
     18        allocation.
     19        * platform/StringImpl.h:
     20        * platform/StringImpl.cpp: (WebCore::StringImpl::adopt): Ditto.
     21
     22        * platform/StreamingTextDecoder.h:
     23        * platform/StreamingTextDecoder.cpp: (WebCore::TextCodec::appendOmittingBOM):
     24        Change to use a Vector<UChar> instead of a String, since vectors have better
     25        resizing performance (they store a separate capacity).
     26
     27        * platform/StreamingTextDecoderICU.cpp: (WebCore::TextCodecICU::decode):
     28        * platform/mac/StreamingTextDecoderMac.cpp: (WebCore::TextCodecMac::decode):
     29        Change to use Vector<UChar> instead of String and then create a string at
     30        the end of the process using the new adopt function.
     31
    1322006-09-28  Sam Weinig  <sam.weinig@gmail.com>
    233
  • trunk/WebCore/platform/PlatformString.h

    r16568 r16622  
    6161
    6262    static String newUninitialized(size_t length, UChar*& characterBuffer);
     63    static String adopt(Vector<UChar>&);
    6364
    6465    operator KJS::Identifier() const;
  • trunk/WebCore/platform/StreamingTextDecoder.cpp

    r16245 r16622  
    4040// We strip BOM characters because they can show up both at the start of content
    4141// and inside content, and we never want them to end up in the decoded text.
    42 void TextCodec::appendOmittingBOM(String& s, const UChar* characters, size_t length)
     42void TextCodec::appendOmittingBOM(Vector<UChar>& v, const UChar* characters, size_t length)
    4343{
    4444    size_t start = 0;
     
    4646        if (BOM == characters[i]) {
    4747            if (start != i)
    48                 s.append(String(&characters[start], i - start));
     48                v.append(&characters[start], i - start);
    4949            start = i + 1;
    5050        }
    5151    }
    5252    if (start != length)
    53         s.append(String(&characters[start], length - start));
     53        v.append(&characters[start], length - start);
    5454}
    5555
  • trunk/WebCore/platform/StreamingTextDecoder.h

    r16245 r16622  
    3131#include <memory>
    3232#include <wtf/Noncopyable.h>
     33#include <wtf/Vector.h>
    3334
    3435namespace WebCore {
     
    4647
    4748    protected:
    48         static void appendOmittingBOM(String&, const UChar*, size_t length);
     49        static void appendOmittingBOM(Vector<UChar>&, const UChar*, size_t length);
    4950    };
    5051
  • trunk/WebCore/platform/StreamingTextDecoderICU.cpp

    r16245 r16622  
    192192    }
    193193
    194     String result = "";
     194    Vector<UChar> result;
    195195
    196196    UChar buffer[ConversionBufferSize];
     
    221221    }
    222222
    223     return result;
     223    return String::adopt(result);
    224224}
    225225
  • trunk/WebCore/platform/String.cpp

    r16568 r16622  
    489489}
    490490
     491String String::adopt(Vector<UChar>& buffer)
     492{
     493    // For an empty buffer, construct an empty string, not a null string,
     494    // and use a standard constructor so we get the shared empty string.
     495    if (buffer.isEmpty())
     496        return "";
     497    return StringImpl::adopt(buffer);
     498}
     499
    491500} // namespace WebCore
    492501
  • trunk/WebCore/platform/StringImpl.cpp

    r16570 r16622  
    10691069}
    10701070
     1071StringImpl* StringImpl::adopt(Vector<UChar>& buffer)
     1072{
     1073    size_t size = buffer.size();
     1074    UChar* data = buffer.releaseBuffer();
     1075    data = static_cast<UChar*>(fastRealloc(data, size * sizeof(UChar)));
     1076
     1077    StringImpl* result = new StringImpl;
     1078    result->m_length = size;
     1079    result->m_data = data;
     1080    return result;
     1081}
     1082
    10711083} // namespace WebCore
  • trunk/WebCore/platform/StringImpl.h

    r16568 r16622  
    6767
    6868    static StringImpl* newUninitialized(size_t length, UChar*& characterBuffer);
     69    static StringImpl* adopt(Vector<UChar>&);
    6970
    7071    const UChar* characters() const { return m_data; }
  • trunk/WebCore/platform/mac/StreamingTextDecoderMac.cpp

    r16245 r16622  
    194194        return String();
    195195   
    196     String result("");
     196    Vector<UChar> result;
    197197
    198198    const unsigned char* sourcePointer = reinterpret_cast<const unsigned char*>(bytes);
     
    254254    }
    255255
     256    String resultString = String::adopt(result);
     257
    256258    // Workaround for a bug in the Text Encoding Converter (see bug 3225472).
    257259    // Simplified Chinese pages use the code U+A3A0 to mean "full-width space".
     
    259261    // To work around, just change all occurences of U+E5E5 to U+3000 (ideographic space).
    260262    if (m_encoding == kCFStringEncodingGB_18030_2000)
    261         result.replace(0xE5E5, 0x3000);
     263        resultString.replace(0xE5E5, 0x3000);
    262264   
    263     return result;
     265    return resultString;
    264266}
    265267
Note: See TracChangeset for help on using the changeset viewer.