Proposal: takeFront and takeBack

Jonathan M Davis jmdavisProg at gmx.com
Wed Jul 4 19:11:13 PDT 2012


On Wednesday, July 04, 2012 21:33:31 Andrei Alexandrescu wrote:
> Great. Could you please post some code so we play with it? Thanks.

Okay. You can use this:

----------
import std.array;
import std.conv;
import std.datetime;
import std.range;
import std.stdio;
import std.string;
import std.traits;
import std.utf;


auto consumeFront(R)(ref R range)
    if(isInputRange!R && !isNarrowString!R)
{
    assert(!range.empty);
    auto retval = range.front;
    range.popFront();
    return retval;
}

auto consumeFront(R)(ref R range)
    if(isNarrowString!R)
{
    size_t index = 0;
    auto retval = decode(range, index);
    range = range[index .. $];
    return retval;
}


void main()
{

    auto origASCII = "hello world, 1234567";
    auto origUni = "ウェブサイト@La_Verité.com";

    void f1()
    {
        auto arr = origASCII;

        while(!arr.empty)
        {
            auto f = arr.front;
            arr.popFront();
        }
    }

    void f2()
    {
        auto arr = origASCII;

        while(!arr.empty)
            auto f = arr.consumeFront();
    }

    void f3()
    {
        auto arr = origUni;

        while(!arr.empty)
        {
            auto f = arr.front;
            arr.popFront();
        }
    }

    void f4()
    {
        auto arr = origUni;

        while(!arr.empty)
            auto f = arr.consumeFront();
    }

    auto result = benchmark!(f1, f2, f3, f4)(10_000_000);
    auto percentage1 = format("%2.02f%%", 100 * result[1].to!("hnsecs", real) 
/ result[0].to!("hnsecs", real));
    auto percentage2 = format("%2.02f%%", 100 * result[3].to!("hnsecs", real) 
/ result[2].to!("hnsecs", real));
    writefln("ascii %s:%s old [%s], new [%s]",
             percentage1,
             std.array.replicate(" ", 7 - percentage1.length),
             to!Duration(result[0]),
             to!Duration(result[1]));
    writefln("uni   %s:%s old [%s], new [%s]",
             percentage2,
             std.array.replicate(" ", 7 - percentage2.length),
             to!Duration(result[2]),
             to!Duration(result[3]));
}
----------

Just adjust the strings to try different strings, and adjust then number of 
iterations if you need to. It prints out a two lines looking like:

ascii 82.89%:  old [5 secs, 176 ms, 602 μs, and 8 hnsecs], new [4 secs, 290 
ms, 683 μs, and 6 hnsecs]
uni   74.78%:  old [6 secs, 876 ms, 3 μs, and 1 hnsec], new [5 secs, 141 ms, 
955 μs, and 6 hnsecs]

where the percentage is the percentage of time that consumeFront uses of the 
time that front and popFront take separately.

To make dealing with the various combinations of compiler flags easier, I 
started using this script:

----------
#!/bin/bash

SRC=$1
TEST=test
TEST_R=testR
TEST_RO=testRO
TEST_ROI=testROI

echo "dmd -w ${SRC} -of${TEST}"
dmd -w "${SRC}" -of"${TEST}" || exit 1
./"${TEST}"
./"${TEST}"
./"${TEST}"

echo ""
echo "dmd -w -release ${SRC} -of${TEST_R}"
dmd -w -release "${SRC}" -of"${TEST_R}" || exit 1
./"${TEST_R}"
./"${TEST_R}"
./"${TEST_R}"

echo ""
echo "dmd -w -release -O ${SRC} -of${TEST_RO}"
dmd -w -release -O "${SRC}" -of"${TEST_RO}" || exit 1
./"${TEST_RO}"
./"${TEST_RO}"
./"${TEST_RO}"

echo ""
echo "dmd -w -release -O -inline ${SRC} -of${TEST_ROI}"
dmd -w -release -O -inline "${SRC}" -of"${TEST_ROI}" || exit 1
./"${TEST_ROI}"
./"${TEST_ROI}"
./"${TEST_ROI}"
----------

You pass it the file that you want to compile, and it'll compile it with 
different combinations of compiler flags and run each combination 3 times.

It shows that consumeFront is clearly faster, but the timings vary a fair bit.

- Jonathan M Davis


More information about the Digitalmars-d mailing list