Skip to content

[SR-12126] String(decoding:as:) allocates if passed an ArraySlice<UInt8> #54561

@weissi

Description

@weissi
Previous ID SR-12126
Radar rdar://problem/59148407
Original Reporter @weissi
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Additional Detail from JIRA
Votes 1
Component/s Standard Library
Labels Bug, Performance
Assignee @milseman
Priority Medium

md5: c7940400704e1e3f7f98b4767867e9a0

Issue 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)
    }
}

Metadata

Metadata

Assignees

Labels

bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.performancestandard libraryArea: Standard library umbrella

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions