Uploaded image for project: 'Swift'
  1. Swift
  2. SR-12126

String(decoding:as:) allocates if passed an ArraySlice<UInt8>

    XMLWordPrintable

    Details

      Description

      String(decoding: arraySlice, as: Unicode.UTF8.self)
      

      allocates (unless the arraySlice is the whole Array).

      Consider the following program

      func makeString<Bytes: Collection>(_ bytes: Bytes) -> String  where Bytes.Element == UInt8 {
          return String(decoding: bytes, as: Unicode.UTF8.self)
      }
      
      func testArraySlice(_ array: ArraySlice<UInt8>) -> String {
          return makeString(array)
      }
      
      @inline(never)
      func doArraySlice() {
          let array: ArraySlice<UInt8> = Array(repeating: UInt8(ascii: "X"), count: 15)[2...]
      
          for _ in 0..<10000 {
              precondition(testArraySlice(array) == "XXXXXXXXXXXXX")
          }
      }
      
      doArraySlice()
      

      which when run as

      swiftc -O test.swift && sudo ~/devel/swift-nio/dev/malloc-aggregation.d -c ./test
      

      prints

      [...]
                    libsystem_malloc.dylib`malloc
                    libswiftCore.dylib`swift_slowAlloc+0x19
                    libswiftCore.dylib`swift_allocObject+0x27
                    test`specialized _ContiguousArrayBuffer.init(_uninitializedCount:minimumCapacity:)+0x39
                    test`specialized Array.init<A>(_:)+0x45
                    test`specialized makeString<A>(_:)+0x162
                    test`doArraySlice()+0xc0
                    test`main+0x9
                    libdyld.dylib`start+0x1
                    test`0x1
                  10000
      

      that's totally unnecessary and can be worked around with

      func makeStringFast<Bytes: Collection>(_ bytes: Bytes) -> String  where Bytes.Element == UInt8 {
          if let string = bytes.withContiguousStorageIfAvailable({
              return String(decoding: $0, as: Unicode.UTF8.self)
          }) {
              return string
          } else {
              return String(decoding: bytes, as: Unicode.UTF8.self)
          }
      }
      

        Attachments

          Activity

            People

            Assignee:
            milseman Michael Ilseman
            Reporter:
            jw Johannes Weiss
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: