Transient ranges
Steven Schveighoffer via Digitalmars-d
digitalmars-d at puremagic.com
Tue May 31 05:42:23 PDT 2016
On 5/30/16 11:46 AM, Andrei Alexandrescu wrote:
> On 05/30/2016 11:22 AM, Steven Schveighoffer wrote:
>> On Monday, 30 May 2016 at 15:12:41 UTC, Andrei Alexandrescu wrote:
>>> On 05/30/2016 09:30 AM, Steven Schveighoffer wrote:
>>>> My iopipe library is 2x as fast.
>>>
>>> Cool! What is the trick to the speedup? -- Andrei
>>
>> Direct buffer access and not using FILE * as a base.
>
> So what primitives do you use? The lower-level descriptor-based
> primitives open() and friends? http://linux.die.net/man/2/open
Yes. That is not the focus of my library, though. I have a very crude
and basic I/O type that just wraps the system calls into a nice API.
> What do you mean by direct buffer access?
I mean instead of pulling data out one character at a time from another
buffer into your buffer, you have direct access, using all the speedups
that CPUs provide when accessing arrays.
I'm also allowing the compiler to inline as much as possible because all
the code is available.
> What is the relative contributions of these (and possibly other) design
> decisions to the overall speed?
I don't know. I started with a vastly different design and it ended up
being twice as fast. So it's difficult to say for certain what are the
major factor that is slowing down std.stdio.
At DConf, Adrian Matoga presented his very similar flod library, and I
was surprised when it was faster than mine at processing lines, even
though he was still using std.stdio.File. So I found a few reasons why
mine was slower and fixed them. The things that made it much faster were:
1. Switched to direct pointer access (i.e. doing while(*ptr++ !=
lineTerminator) {} ) when the buffer type was an array.
2. I was stupidly accessing the member of the struct which held the
terminator instead of allocating a stack variable for it. After doing
that (and making it immutable), the compiler was much better informed on
how to optimize.
There may even be more opportunities for speedup, but I'm pretty
satisfied with it at the moment.
> How can we integrate some of these in std.stdio without breaking
> backward compatibility,
There are 2 main issues with FILE *:
1) it does not provide buffer access, so you must rely on things like
getline if they exist. But these have their own problems (i.e. do not
support unicode, require C-malloc'd buffer)
2) All calls are opaque, so no inlining can occur. This is especially
painful if you have to call fgetc in a tight loop. This goes back to the
buffer access issue -- FILE * only lets you look ahead one character.
So I think the only real way to provide a decent performance improvement
without breaking C compatibility is to write code that is aware of the
implementation details of the opaque FILE * type. Just like getline.
> or offer additional artifacts that integrate
> seamlessly and don't need to be compatible?
I had a grand plan to replace stdio with something that "evolves" to
faster D based i/o when you did D-like things. But it's very complex,
and each addition of code to stdio makes things more complex.
In reality, I think we only need to be C compatible for stdout (possibly
only via write[f][ln]), and possibly stdin. There's no reason we need to
use C i/o for any other uses. What makes things difficult is that
everything in Phobos uses std.stdio.File for all i/o and that uses C i/o.
-Steve
More information about the Digitalmars-d
mailing list