<font size=2 face="sans-serif">As suggested, I created a pull request
for the String manifesto adding an unsafe String API discussion.</font><br><a href=https://github.com/apple/swift/pull/7479><font size=2 color=blue face="sans-serif">https://github.com/apple/swift/pull/7479</font></a><br><br><font size=2 face="sans-serif">I included in the comments a tentative
implementation in Swift 3.</font><br><a href=https://gist.github.com/tardieu/7ca43d19b6197033dc39b138ba0e500e><font size=2 color=blue face="sans-serif">https://gist.github.com/tardieu/7ca43d19b6197033dc39b138ba0e500e</font></a><br><br><font size=2 face="sans-serif">I focused for now on the most essential
capabilities that, hopefully, are not too controversial.</font><br><br><font size=2 face="sans-serif">Regards,</font><br><br><font size=2 face="sans-serif">Olivier</font><br><br><br><tt><font size=2>dabrahams@apple.com wrote on 01/31/2017 02:23:49 PM:<br><br>&gt; From: Dave Abrahams &lt;dabrahams@apple.com&gt;</font></tt><br><tt><font size=2>&gt; To: Olivier Tardieu/Watson/IBM@IBMUS</font></tt><br><tt><font size=2>&gt; Cc: Ben Cohen &lt;ben_cohen@apple.com&gt;, swift-evolution
&lt;swift-<br>&gt; evolution@swift.org&gt;</font></tt><br><tt><font size=2>&gt; Date: 01/31/2017 02:24 PM</font></tt><br><tt><font size=2>&gt; Subject: Re: [swift-evolution] Strings in Swift
4</font></tt><br><tt><font size=2>&gt; Sent by: dabrahams@apple.com</font></tt><br><tt><font size=2>&gt; <br>&gt; <br>&gt; on Mon Jan 30 2017, Olivier Tardieu &lt;tardieu-AT-us.ibm.com&gt;
wrote:<br>&gt; <br>&gt; &gt; Thanks for the clarifications.<br>&gt; &gt; More comments below.<br>&gt; &gt;<br>&gt; &gt; dabrahams@apple.com wrote on 01/24/2017 05:50:59 PM:<br>&gt; &gt;<br>&gt; &gt;&gt; Maybe it wasn't clear from the document, but the intention
is that<br>&gt; &gt;&gt; String would be able to use any model of Unicode as a backing
store, and<br>&gt; &gt;&gt; that you could easily build unsafe models of Unicode... but
also that<br>&gt; &gt;&gt; you could use your unsafe model of Unicode directly, in string-ish
ways.<br>&gt; &gt;<br>&gt; &gt; I see. If I understand correctly, it will be possible for instance
to <br>&gt; &gt; implement an unsafe model of Unicode with a UInt8 code unit and
a <br>&gt; &gt; maxLengthOfEncodedScalar equal to 1 by only keeping the 8 lowest
bits of <br>&gt; &gt; Unicode scalars.<br>&gt; <br>&gt; Eh... I think you'd just use an unsafe Latin-1 for that; why waste
a<br>&gt; bit?<br>&gt; <br>&gt; Here's an example (work very much in-progress):<br>&gt; </font></tt><a href=https://github.com/apple/swift/blob/><tt><font size=2>https://github.com/apple/swift/blob/</font></tt></a><tt><font size=2><br>&gt; 9defe9ded43c6f480f82a28d866ec73d803688db/test/Prototypes/Unicode.swift#L877<br>&gt; <br>&gt; <br>&gt; &gt;&gt; &gt; A lot of machine processing of strings continues to
deal with 8-bit<br>&gt; &gt;&gt; &gt; quantities (even 7-bit quantities, not UTF-8). &nbsp;Swift
strings are<br>&gt; &gt;&gt; &gt; not very good at that. I see progress in the manifesto
but nothing<br>&gt; &gt;&gt; &gt; to really close the performance gap with C. &nbsp;That's
where &quot;unsafe&quot;<br>&gt; &gt;&gt; &gt; mechanisms could come into play.<br>&gt; &gt;&gt; <br>&gt; &gt;&gt; extendedASCII is supposed to address that. &nbsp;Given a
smart enough<br>&gt; &gt;&gt; optimizer, it should be possible to become competitive with
C even<br>&gt; &gt;&gt; without using unsafe constructs. &nbsp;However, we recognize
the importance<br>&gt; &gt;&gt; of being able to squeeze out that last bit of performance
by dropping<br>&gt; &gt;&gt; down to unsafe storage.<br>&gt; &gt;<br>&gt; &gt; I doubt a 32-bit encoding can bridge the performance gap with
C in<br>&gt; &gt; particular because wire protocols will continue to favor compact<br>&gt; &gt; encodings. &nbsp;Incoming strings will have to be expanded to
the<br>&gt; &gt; extendedASCII representation before processing and probably compacted<br>&gt; &gt; afterwards. So while this may address the needs of computationally<br>&gt; &gt; intensive string processing tasks, this does not help simple
parsing<br>&gt; &gt; tasks on simple strings.<br>&gt; <br>&gt; I'm pretty sure it does; we're not going to change representations<br>&gt; <br>&gt; extendedASCII doesn't require anything to actually be expanded to<br>&gt; 32-bits per code unit, except *maybe* in a register, and then only
if<br>&gt; the optimizer isn't smart enough to eliminate zero-extension followed
by<br>&gt; comparison with a known narrow value. &nbsp;You can always<br>&gt; <br>&gt; &nbsp; latin1.lazy.map { UInt32($0) }<br>&gt; <br>&gt; to produce 32-bit code units. &nbsp;All the common encodings are ASCII<br>&gt; supersets, so this will “just work” for those. &nbsp;The only places
where it<br>&gt; becomes more complicated is in encodings like Shift-JIS (which might
not<br>&gt; even be important enough to support as a String backing-storage format).<br>&gt; <br>&gt; &gt;<br>&gt; &gt;&gt; &gt; To guarantee Unicode correctness, a C string must be
validated or <br>&gt; &gt;&gt; &gt; transformed to be considered a Swift string.<br>&gt; &gt;&gt; <br>&gt; &gt;&gt; Not really. &nbsp;You can do error-correction on the fly.
&nbsp;However, I think<br>&gt; &gt;&gt; pre-validation is often worthwhile because once you know
something is<br>&gt; &gt;&gt; valid it's much cheaper to decode correctly (especially for
UTF-8).<br>&gt; &gt;<br>&gt; &gt; Sure. Eager vs. lazy validation is a valuable distinction, but
what I am <br>&gt; &gt; after here is side-stepping validation altogether. I understand
now that <br>&gt; &gt; user-defined encodings will make side-stepping validation possible.<br>&gt; <br>&gt; Right.<br>&gt; <br>&gt; &gt;<br>&gt; &gt;&gt; &gt; If I understand the C String interop section correctly,
in Swift 4,<br>&gt; &gt;&gt; &gt; this should not force a copy, but traversing the string
is still<br>&gt; &gt;&gt; &gt; required. <br>&gt; &gt;&gt; <br>&gt; &gt;&gt; *What* should not force a copy?<br>&gt; &gt;<br>&gt; &gt; I would like to have a constructor that takes a pointer to a
<br>&gt; &gt; null-terminated sequence of bytes (or a sequence of bytes and
a length) <br>&gt; &gt; and turns it into a Swift string without allocation of a new
backing store <br>&gt; &gt; for the string and without copying the bytes in the sequence
from one <br>&gt; &gt; place in memory to another. <br>&gt; <br>&gt; We probably won't expose this at the top level of String, but you
should<br>&gt; be able to construct an UnsafeCString (which is-a Unicode) and then,
if<br>&gt; you really need the String type, construct a String from that:<br>&gt; <br>&gt; &nbsp; &nbsp;String(UnsafeCString(ntbs))<br>&gt; <br>&gt; That would not do any copying.<br>&gt; <br>&gt; &gt; I understand this may require the programmer to handle memory<br>&gt; &gt; management for the backing store.<br>&gt; &gt;<br>&gt; &gt;&gt; &gt; I hope I am correct about the no-copy thing, and I would
also like to<br>&gt; &gt;&gt; &gt; permit promoting C strings to Swift strings without
validation. &nbsp;This<br>&gt; &gt;&gt; &gt; is obviously unsafe in general, but I know my strings...
and I care<br>&gt; &gt;&gt; &gt; about performance. ;)<br>&gt; &gt;&gt; <br>&gt; &gt;&gt; We intend to support that use-case. &nbsp;That's part of
the reason for the<br>&gt; &gt;&gt; ValidUTF8 and ValidUTF16 encodings you see here:<br>&gt; &gt;&gt; </font></tt><a href="https://github.com/apple/swift/blob/unicode-rethink/stdlib/public/"><tt><font size=2>https://github.com/apple/swift/blob/unicode-rethink/stdlib/public/</font></tt></a><tt><font size=2><br>&gt; &gt;&gt; core/Unicode2.swift#L598<br>&gt; &gt;&gt; and here:<br>&gt; &gt;&gt; </font></tt><a href="https://github.com/apple/swift/blob/unicode-rethink/stdlib/public/"><tt><font size=2>https://github.com/apple/swift/blob/unicode-rethink/stdlib/public/</font></tt></a><tt><font size=2><br>&gt; &gt;&gt; core/Unicode2.swift#L862<br>&gt; &gt;<br>&gt; &gt; OK<br>&gt; &gt;<br>&gt; &gt;&gt; &gt; More importantly, it is not possible to mutate bytes
in a Swift string<br>&gt; &gt;&gt; &gt; at will. &nbsp;Again it makes sense from the point of
view of always<br>&gt; &gt;&gt; &gt; correct Unicode sequences. &nbsp;But it does not for
machine processing of<br>&gt; &gt;&gt; &gt; C strings with C-like performance. &nbsp;Today, I can
cheat using a<br>&gt; &gt;&gt; &gt; &quot;_public&quot; API for this, i.e., myString._core.
&nbsp;_baseAddress!. &nbsp;This<br>&gt; &gt;&gt; &gt; should be doable from an official &quot;unsafe&quot;
API.<br>&gt; &gt;&gt; <br>&gt; &gt;&gt; We intend to support that use-case.<br>&gt; &gt;&gt; <br>&gt; &gt;&gt; &gt; Memory safety is also at play here, as well as ownership.
&nbsp;A proper<br>&gt; &gt;&gt; &gt; API could guarantee the backing store is writable for
instance, that<br>&gt; &gt;&gt; &gt; it is not shared. &nbsp;A memory-safe but not unicode-safe
API could do<br>&gt; &gt;&gt; &gt; bounds checks.<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; While low-level C string processing can be done using
unsafe memory<br>&gt; &gt;&gt; &gt; buffers with performance, the lack of bridging with
&quot;real&quot; Swift<br>&gt; &gt;&gt; &gt; strings kills the deal. &nbsp;No literals syntax (or
costly coercions),<br>&gt; &gt;&gt; &gt; none of the many useful string APIs.<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; To illustrate these points here is a simple experiment:
code written<br>&gt; &gt;&gt; &gt; to synthesize an http date string from a bunch of integers.
&nbsp;There are<br>&gt; &gt;&gt; &gt; four versions of the code going from nice high-level
Swift code to<br>&gt; &gt;&gt; &gt; low-level C-like code. &nbsp;(Some of this code is also
about avoiding ARC<br>&gt; &gt;&gt; &gt; overheads, and string interpolation overheads, hence
the four<br>&gt; &gt;&gt; &gt; versions.)<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; On my macbook pro (swiftc -O), the performance is as
follows:<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; interpolation + func: &nbsp;2.303032365s<br>&gt; &gt;&gt; &gt; interpolation + array: 1.224858418s<br>&gt; &gt;&gt; &gt; append: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;0.918512377s<br>&gt; &gt;&gt; &gt; memcpy: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;0.182104674s<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; While the benchmarking could be done more carefully,
I think the main<br>&gt; &gt;&gt; &gt; observation is valid. &nbsp;The nice code is more than
10x slower than the<br>&gt; &gt;&gt; &gt; C-like code. &nbsp;Moreover, the ugly-but-still-valid-Swift
code is still<br>&gt; &gt;&gt; &gt; about 5x slower than the C like code. &nbsp;For some
applications, e.g. web<br>&gt; &gt;&gt; &gt; servers, this kind of numbers matter...<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; Some of the proposed improvements would help with this,
e.g., small<br>&gt; &gt;&gt; &gt; strings optimization, and maybe changes to the concatenation<br>&gt; &gt;&gt; &gt; semantics. &nbsp;But it seems to me that a big performance
gap will remain.<br>&gt; &gt;&gt; &gt; (Concatenation even with strncat is significantly slower
than memcpy<br>&gt; &gt;&gt; &gt; for fixed-size strings.)<br>&gt; &gt;&gt; &gt;<br>&gt; &gt;&gt; &gt; I believe there is a need and an opportunity for a fast
&quot;less safe&quot;<br>&gt; &gt;&gt; &gt; String API. &nbsp;I hope it will be on the roadmap soon.<br>&gt; &gt;&gt; <br>&gt; &gt;&gt; I think it's already in the roadmap...the one that's in my
head. &nbsp;If you<br>&gt; &gt;&gt; want to submit a PR with amendments to the manifesto, that'd
be great.<br>&gt; &gt;&gt; Also thanks very much for the example below; we'll definitely<br>&gt; &gt;&gt; be referring to it as we proceed forward.<br>&gt; &gt;<br>&gt; &gt; Here is a gist for the example code:<br>&gt; &gt; </font></tt><a href=https://gist.github.com/tardieu/b6a9c4d53d56d089c58089ba8f6274b5><tt><font size=2>https://gist.github.com/tardieu/b6a9c4d53d56d089c58089ba8f6274b5</font></tt></a><tt><font size=2><br>&gt; &gt;<br>&gt; &gt; I can sketch key elements of an unsafe String API and some motivating
<br>&gt; &gt; arguments in a pull request. Is this what you are asking for?<br>&gt; <br>&gt; That would be awesome, thanks!<br>&gt; <br>&gt; -- <br>&gt; -Dave<br>&gt; <br></font></tt><BR>