Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-133737

QByteArray::replace() is not linear when replacement.size() > needle.size()

    XMLWordPrintable

Details

    • Task
    • Resolution: Unresolved
    • P2: Important
    • None
    • None
    • None

    Description

      The algorithm used in at least replace(QByteArrayView, QByteArrayView) is faulty in that it produces quadratic runtime at least when the replacement is longer than the needle:

      ********* Start testing of tst_QByteArray *********
      Config: Using QtTest library 6.10.0, Qt 6.10.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by Clang 15.0.3 (github.com:llvm/llvm-project.git 48b23aa469b8cfdb6cde1c55bf3361cabcdef6bc)), ubuntu 20.04
      PASS   : tst_QByteArray::initTestCase()
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(001 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"001 MiB":
           12 msecs per iteration (total: 12, iterations: 1)
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(002 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"002 MiB":
           31 msecs per iteration (total: 31, iterations: 1)
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(004 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"004 MiB":
           141 msecs per iteration (total: 141, iterations: 1)
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(008 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"008 MiB":
           526 msecs per iteration (total: 526, iterations: 1)
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(016 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"016 MiB":
           3,293 msecs per iteration (total: 3,293, iterations: 1)
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(032 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"032 MiB":
           17,169 msecs per iteration (total: 17,169, iterations: 1)
      PASS   : tst_QByteArray::replaceWithLongerIsLinear(064 MiB)
      RESULT : tst_QByteArray::replaceWithLongerIsLinear():"064 MiB":
           81,379 msecs per iteration (total: 81,379, iterations: 1)
      ^CReceived signal 2 (SIGINT)
               replaceWithLongerIsLinear function time: 374950ms, total time: 374951ms
      

      (manual kill)

      Expected: each step takes 2x as long as the previous one. Actually, it takes more than 4x as long, so it's quadratic.

      Replacement is an inherently linear operation. For it to take quadratic time is not acceptable.

      The following is the sketch of a linear operation:

      QByteArray res;
      QByteArrayView sep;
      for (auto part : qTokenize(QLatin1StringView{haystack}, QLatin1StringView{replacement}) {
          res += sep;
          res += QByteArrayView{part};
          sep = replacement;
      }
      return res;
      

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              cnn Qt Core & Network
              mmutz Marc Mutz
              Vladimir Minenko Vladimir Minenko
              Alex Blasche Alex Blasche
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes