[Issue 8219] New: File.writeln is slow

d-bugmail at puremagic.com d-bugmail at puremagic.com
Mon Jun 11 05:18:03 PDT 2012


http://d.puremagic.com/issues/show_bug.cgi?id=8219

           Summary: File.writeln is slow
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody at puremagic.com
        ReportedBy: bearophile_hugs at eml.cc


--- Comment #0 from bearophile_hugs at eml.cc 2012-06-11 05:20:08 PDT ---
A little benchmark to show the low performance of the
std.stdio.File().writeln() with numbers. The programs accept N from the command
line, and just save a textual file (opened as binary file) that contains
numbers from 0 to N-1. 

The write1 program is the basic one that uses File.writeln(). The successive
programs are for comparison.

The write2 program is equally basic, but it uses C functions, using the same D
compiler and compilation arguments, and it's almost 12 times faster.

The write3 program is a basic Java program, it's more than 17 times faster than
write1.

The write4 is a test to write a very fast D program, it's more than 30 times
faster than write2 (it's not the fastest possible program because the DMD
compiler is currently not able to perform the small dividend optimization. GCC
and Clang are able to replace the small dividend with some faster operations).


DMD 2.060alpha, Windows, -O -release -inline
Java 1.7.0_03-b05

Timings, N = 2_000_000, best of 3, seconds:
  write1: 9.67
  write2: 0.83 
  write3: 0.56 (Java)
  write4: 0.32

- - - - - - - - - - - - - - - - - - - - - - - - -

// write1
import std.stdio, std.conv;

void main(string[] args) {
    auto f = File("numbers.txt", "wb");
    foreach (i; 0 .. args[1].to!int())
        f.writeln(i);
    f.close();
}

- - - - - - - - - - - - - - - - - - - - - - - - -

// write2
import core.stdc.stdio, std.conv;

void main(string[] args) {
    auto f = fopen("numbers.txt", "wb");
    foreach (i; 0 .. args[1].to!int())
        fprintf(f, "%d\n", i);
    fclose(f);
}

- - - - - - - - - - - - - - - - - - - - - - - - -

// write3
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

class write3 {
    public static void main(String args[]) {
        if (args.length != 1)
            System.exit(-1);
        int count = Integer.parseInt(args[0]);

        try {
            BufferedWriter bw = new BufferedWriter(new
FileWriter("numbers.txt"));

            for (int i = 0; i < count; i++) {
                bw.write(i);
                bw.write("\n");
            }

            bw.close();
        } catch (IOException e) {
            System.exit(-2);
        }
    }
}

- - - - - - - - - - - - - - - - - - - - - - - - -

// write4
import core.stdc.stdio, std.conv, std.typetuple;

void saveNumbers(uint buf_size)(FILE* f, in uint n, in uint start) nothrow {
    __gshared static char[buf_size] buffer = void;
    __gshared static immutable string digits = "0123456789";
    char* ptr = buffer.ptr;

    foreach (k; start .. start + n) {
        uint v = k;
        if (v >= 0 && v < 10) {
            *ptr = digits[v];
            ptr++;
        } else {
            if (v < 0) {
                v = -v;
                *ptr = '-';
                ptr++;
            }

            char* start_ptr = ptr;

            foreach (_; TypeTuple!(0,1,2,3,4,5,6,7,8,9)) {
                // DMD doesn't know how to perform a fast division
                // or modulus when the quotient is a small integer
                *ptr = (v % 10) + '0';
                v /= 10;
                ptr++;
                if (!v) break;
            }

            immutable size_t i = ptr - start_ptr;
            for (size_t j = 0; j < i / 2; ++j) {
                immutable aux = start_ptr[j];
                start_ptr[j] = start_ptr[i - j - 1];
                start_ptr[i - j - 1] = aux;
            }
        }
        *ptr = '\n';
        ptr++;
    }

    *ptr = '\0';
    fputs(buffer.ptr, f);
}

void main(in string[] args) {
    auto f = fopen("numbers.txt", "wb");
    if (args.length != 2 || f == null) return;
    immutable uint N = to!uint(args[1]);

    enum uint max_int_len = 12;
    enum uint buf_size = 1_000_000;
    enum uint M = buf_size / max_int_len;

    uint count;
    foreach (_0; 0 .. N / M) {
        saveNumbers!buf_size(f, M, count);
        count += M;
    }
    saveNumbers!buf_size(f, N % M, count);

    fclose(f);
}

- - - - - - - - - - - - - - - - - - - - - - - - -

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list