[D-runtime] foreach (dchar c; s) is too slow
Jonathan M Davis
jmdavisProg at gmx.com
Tue Oct 1 11:13:09 PDT 2013
On Monday, September 30, 2013 20:47:52 Martin Nowak wrote:
> The runtime support for string foreach with decoding has some serious
> performance issues.
> It's currently implemented by creating a delegate for the foreach body
> and calling _aApply*.
> I recently submitted this pull to vibe.d
> https://github.com/rejectedsoftware/vibe.d/pull/327.
> Using the explicit for (auto tmp = s; !tmp.empty; tmp.popFront()) { auto
> c = tmp.front; /*CODE*/ }
> is about 3 times faster.
> I'd like to avoid such hidden performance pitfalls. Any ideas how to
> transition to templated library code?
> For dchar iteration the compiler could simply prefer the range
> interface, but that wouldn't work for wchar (or char with w/dstrings).
> Is it something that should only be added to phobos, e.g. foreach (c;
> s.byChar!dchar())?
> Or should this be a combination of compiler and library support, i.e.
> when an explicit char type is given the compiler
> instantiates a template with that char type.
The range API won't even work on arrays unless std.array has been imported,
and in the case of strings, it depends on std.utf. So, using the range
interface underneat the hood for
foreach(dchar c; str)
would require Phobos. I'd argue for simply fixing how foreach for strings works
so that it doesn't use opApply. Worst case, some druntime-specific functions
could be written and used to do it, though that would probably require changes
in the compiler. But if you want to use a range of some kind, just create one
for each character type, and the fact that Phobos treats strings as ranges of
dchar should be irrelevant. It does that by having traits like hasLength and
isNarrowString treat them that way. There's no reason why you can't have a
range of char or wchar if you want to, and if druntime is wrapping strings in
ranges for foreach, then it can trivially create a range type which treats
strings as ranges of whatever character type you want just so long as front
and popFront do the appropriate conversion. Probably another thing to consider
in all this is how to deal with foreach_reverse, but that can probably be
dealt with as well.
I don't particularly like the fact that we're forced to duplicate std.utf stuff
in druntime in order to handle foreach, but I don't know of any way around
that short of moving std.utf (or some portion of it) into druntime. It's
pretty much the same problem that we have with the fact that std.traits isn't
available in druntime, except that the implementation for decode and stride
are a bit more complicated than most traits.
- Jonathan M Davis
More information about the D-runtime
mailing list