Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimization For Array Overload of std.conv.parse #5018

Merged
merged 3 commits into from
Feb 12, 2017

Conversation

JackStouffer
Copy link
Member

@JackStouffer JackStouffer commented Jan 5, 2017

LDC

# new
Total time: 6 secs, 244 ms, 694 μs, and 2 hnsecs

# old
Total time: 8 secs, 555 ms, 476 μs, and 5 hnsecs

DMD

# new
Total time: 10 secs, 220 ms, 605 μs, and 5 hnsecs

# old
Total time: 14 secs, 600 ms, 397 μs, and 1 hnsec

Code

import std.stdio;
import std.range;
import std.algorithm;
import std.traits;
import std.container;
import std.meta;
import std.conv;
import std.datetime;

Target parse1(Target, Source)(ref Source s, dchar lbracket = '[', dchar rbracket = ']', dchar comma = ',')
    if (isSomeString!Source && !is(Source == enum) &&
        isDynamicArray!Target && !is(Target == enum))
{
    import std.array : appender;

    auto result = appender!Target();

    parseCheck!s(lbracket);
    skipWS(s);
    if (s.empty)
        throw new ConvException("");
    if (s.front == rbracket)
    {
        s.popFront();
        return result.data;
    }
    for (;; s.popFront(), skipWS(s))
    {
        result ~= parseElement!(ElementType!Target)(s);
        skipWS(s);
        if (s.empty)
            throw new ConvException("");
        if (s.front != comma)
            break;
    }
    parseCheck!s(rbracket);

    return result.data;
}

void skipWS(R)(ref R r)
{
    import std.ascii : isWhite;
    static if (isSomeString!R)
    {
        //Implementation inspired from stripLeft.
        foreach (i, dchar c; r)
        {
            if (!isWhite(c))
            {
                r = r[i .. $];
                return;
            }
        }
        r = r[0 .. 0]; //Empty string with correct type.
        return;
    }
    else
    {
        for (; !r.empty && isWhite(r.front); r.popFront())
        {}
    }
}

void parseCheck(alias source)(dchar c, string fn = __FILE__, size_t ln = __LINE__)
{
    if (source.empty)
        throw new ConvException(text("unexpected end of input when expecting", "\"", c, "\""));
    if (source.front != c)
        throw new ConvException(text("\"", c, "\" is missing"), fn, ln);
    source.popFront();
}

__gshared char[] test = ['[', '1', ',', '2', ',', '3', ',', '4', ',', '5', ']'];

void main()
{
    enum n = 20_000_000;

    int[] result;
    StopWatch sw;
    Duration sum;
    TickDuration last = TickDuration.from!"seconds"(0);

    foreach(i; 0 .. n)
    {
        sw.start();

        // New
        result = parse1!(int[])(test);

        // Old
        //result = parse!(int[])(test);

        sw.stop();

        test = ['[', '1', ',', '2', ',', '3', ',', '4', ',', '5', ']'];
        auto time = sw.peek() - last;
        last = sw.peek();

        sum += time.to!Duration();
    }

    writeln("Total time: ", sum);
}

@UplinkCoder
Copy link
Member

UplinkCoder commented Jan 26, 2017

Your comment is just a hunk of code.
Please explain what you did.

in this case:
"Used appender instead of dynamic array."

this will pissmize performance in some cases.

@JackStouffer
Copy link
Member Author

Your comment is just a hunk of code.

This code is the performance benchmark.

Please explain what you did.

Replaced the dynamic array with an Appender.

this will pissmize performance in some cases.

Please give an example.

Copy link
Member

@wilzbach wilzbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - Appender is a lot more opportunitistic in pre-allocating memory than D's builtin Array. Though I it would never hurt to fine tune that as well ;-)

@JackStouffer
Copy link
Member Author

Auto-merge toggled on

@JackStouffer JackStouffer merged commit eb15392 into dlang:master Feb 12, 2017
@JackStouffer JackStouffer deleted the parse-decoding branch February 12, 2017 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants