Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-7136] Fast-path ad-hoc printing of Strings #49684

Open
jckarter opened this issue Mar 7, 2018 · 10 comments
Open

[SR-7136] Fast-path ad-hoc printing of Strings #49684

jckarter opened this issue Mar 7, 2018 · 10 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. good first issue Good for newcomers standard library Area: Standard library umbrella

Comments

@jckarter
Copy link
Member

jckarter commented Mar 7, 2018

Previous ID SR-7136
Radar None
Original Reporter @jckarter
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Bug, StarterBug
Assignee None
Priority Medium

md5: 2686733126be82154b524085fb9de797

Issue Description:

Using Strings with print, string interpolation, String(describing:), etc., is extremely common, but goes through the generic protocol testing dispatch mechanism everything does. We should dynamically check whether something is a String and just print the string.

@jckarter
Copy link
Member Author

jckarter commented Mar 7, 2018

Starter bug potential implementation: Look for _print_unlocked in the standard library, and add an early `if let string = value as? String` path.

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 9, 2018

Comment by Yuki Kuroda (JIRA)

I tried this issue with this PR.

@milseman
Copy link
Mannequin

milseman mannequin commented Mar 9, 2018

@jckarter darquro (JIRA User) do you have code observing this slowdown? Can we add it to our regression benchmarks?

@jckarter
Copy link
Member Author

jckarter commented Mar 9, 2018

@nicklockwood observed on Twitter that string interpolation was 100x slower than append()-ing:

https://twitter.com/nicklockwood/status/971506873387143168

Maybe he can share his microbenchmark?

@nicklockwood
Copy link
Contributor

Sorry everyone, it turns out I'm an idiot. I was comparing

foo = "(foo)bar"

against

foo += "bar"

and not

foo = foo + "bar"

which of course is not a fair comparison since the former is updating in place, and the latter is copying the buffer each time.

I re-ran the benchmark and found that interpolation is almost identical to using +.

I did, however discover that foo.appending(bar) is significantly slower than foo + bar, so maybe there's something worth investigating there?

Benchmark: https://gist.github.com/nicklockwood/9a5b846f9535c1f1e5743429a9ccd71f

My results:

@jckarter
Copy link
Member Author

jckarter commented Mar 9, 2018

Thanks for following up @nicklockwood! I wonder whether the difference in `+` and `appending` comes down to the difference in their calling conventions, since as currently implemented Swift will pass regular function arguments at +1 and 'self' at +0. Both operations would be strong candidates for passing at +1 when we add keywords for controlling the calling convention, since it would be useful for both functions to do an in-place append when one of the arguments is passed in the unique reference to a buffer.

@milseman
Copy link
Mannequin

milseman mannequin commented Mar 9, 2018

How does +1 improve things here? For Array, you have the chance to become the last use of a non-trivial single-element append. But with String, you're always copying the underlying code units, which are trivial.

@jckarter
Copy link
Member Author

jckarter commented Mar 9, 2018

I suppose it has the most benefit for only the left hand side of the append, since you can do a \+= instead of a \+ and avoid quadratically moving any memory on the left-hand side. There wouldn't be much benefit to consuming the rhs, you're right.

@milseman
Copy link
Mannequin

milseman mannequin commented Mar 9, 2018

Also, the standard library doesn't implement `appending` for String. You're getting the one from https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/NSStringAPI.swift#L1011, where the Foundation overlay implements something with a bunch of potential bridging and copying back and forth.

These should really be reconciled into some kind of consistent story, ala https://forums.swift.org/t/rfd-reconciling-nsstring-and-string/10350

CC Lance (JIRA User)

edit: grammar and CC

@Moximillian
Copy link
Contributor

The simple appending case for String could be improved just by providing specific extension... Although the example below is probably not the best way to do it.

extension String {

public func appending(_ aString: String) -> String {

var s = self

s.append(aString)

return s

}

}

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. good first issue Good for newcomers standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

4 participants