Skip to content

A faster replacement for a subset of std.stdio module from D language

License

Notifications You must be signed in to change notification settings

competitive-dlang/speedy-stdio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

speedy-stdio

Do you have a program implemented in D programming language, which somehow needs to read and parse gigantic amounts of text from stdin and then write gigantic amounts of text to stdout? If the answer is "yes", then this library may be interesting for you.

Dub version Dub downloads License dmd and ldc gdc

The speedy.stdio module extends std.stdio by substituting functions write, writeln, writef and writefln with faster replacements. These replacements are optimized to handle only the most basic format variants (decimal integers and non-escaped strings), but do it very fast. They are also compatible with the @nogc attribute as an extra bonus. More complicated format variants are still handled transparently via having a fallback to std.format.write.formattedWrite for full compatibility with Phobos (but whenever such fallbacks are used, the performance and @nogc compatibility is lost).

Another bundled speedy.fakestdio module only imitates the API of std.stdio, but cuts some extra corners for additional speed. It is not thread-safe and it also assumes that it has exclusive monopoly to access stdout (doesn't play nice together with printf or with the original functions from the real std.stdio inside of the same program). Also it only imitates stdout.flush and has no support for the other methods of std.stdio.File. Use with caution! But this is good enough for use in solutions submitted to competitive programming platforms, such as Codeforces or AtCoder.

Example

A 99 bottles of beer example code, intentionally using different varieties of functions:

/+dub.sdl:
dependency "speedy-stdio" version="~>0.2.0"
+/
@safe @nogc:         // note: remove @nogc to compile with the standard "std.stdio"
import speedy.stdio; // this can be also "std.stdio" or "speedy.fakestdio"
const repeats = 1;   // change this to something much larger when benchmarking

void main() {
  foreach (i ; 0 .. repeats) {
    auto bottles(int n) { return n == 1 ? " bottle" : " bottles"; }
    foreach_reverse(n ; 1 .. 100) {
      writefln!"%d%s of beer on the wall, %d%s of beer."(n, bottles(n), n, bottles(n));
      static immutable a = ["Take", "one", "down", "and", "pass", "it", "around"];
      a.writef!"%-(%s %), ";
      if (n - 1 <= 0)
        write("no more bottles");
      else
        write(n - 1, bottles(n - 1));
      writeln(" of beer on the wall.");
      writeln;
    }
    writeln("No more bottles of beer on the wall, no more bottles of beer.");
    writeln("Go to the store and buy some more, 99 bottles of beer on the wall.");
  }
}

Install the DUB package manager and run the example in a script-like fashion:

$ dub bottles.d

Or compile an optimized binary using the LDC compiler:

$ dub build --build release --single --compiler=ldc2 bottles.d

Performance

Changing "repeats" to 100000 in the "99 bottles of beer" example above and running it on a Linux system with Intel Core i7-860 @2.8GHz processor and LDC 1.30.0 compiler produces the following results (redirected to /dev/null):

used module test code repeats compiler time
std.stdio 99 bottles of beer 100000 LDC 1.30.0 17.874s
speedy.stdio 99 bottles of beer 100000 LDC 1.30.0 4.749s
speedy.fakestdio 99 bottles of beer 100000 LDC 1.30.0 1.749s

Another benchmark is just printing numbers from 0 to 100M on each line (redirected to /dev/null):

/+dub.sdl:
dependency "speedy-stdio" version="~>0.2.0"
+/
@safe @nogc:         // note: remove @nogc to compile with the standard "std.stdio"
import speedy.stdio; // this can be also "std.stdio" or "speedy.fakestdio"

void main() {
  import std.range;
  100000001.iota.writefln!"%(%d\n%)";
}
used module test code compiler time
std.stdio count to 100M LDC 1.30.0 17.520s
speedy.stdio count to 100M LDC 1.30.0 2.349s
speedy.fakestdio count to 100M LDC 1.30.0 1.809s

About

A faster replacement for a subset of std.stdio module from D language

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages