Skip to content

Conversation

@JackStouffer
Copy link
Contributor

Results:

$ ldc2 -O -release test.d && ./test
old	8 secs, 786 ms, 105 μs, and 7 hnsecs
new	997 ms, 166 μs, and 6 hnsecs

$ dmd -O -inline -release test.d && ./test
old	18 secs, 190 ms, 732 μs, and 1 hnsec
new	2 secs, 646 ms, 737 μs, and 2 hnsecs

See #6062 for earlier examples of this type of PR

Benchmark code:

import std.stdio;
import std.algorithm;
import std.conv;
import std.ascii;
import std.range;
import std.traits;
import std.string;
import std.datetime.date;
import std.datetime.stopwatch;
import std.utf;

enum testCount = 20_000_000;

Date fromSimpleString1(S)(in S simpleString) @safe pure
        if (isSomeString!(S))
{
    import std.algorithm.searching : all, startsWith;
    import std.ascii : isDigit;
    import std.conv : to;
    import std.exception : enforce;
    import std.format : format;
    import std.string : strip;

    auto dstr = to!dstring(strip(simpleString));

    enforce(dstr.length >= 11, new DateTimeException(format("Invalid string format: %s", simpleString)));

    auto day = dstr[$-2 .. $];
    auto month = monthFromString(to!string(dstr[$-6 .. $-3]));
    auto year = dstr[0 .. $-7];

    enforce(dstr[$-3] == '-', new DateTimeException(format("Invalid string format: %s", simpleString)));
    enforce(dstr[$-7] == '-', new DateTimeException(format("Invalid string format: %s", simpleString)));
    enforce(all!isDigit(day), new DateTimeException(format("Invalid string format: %s", simpleString)));

    if (year.length > 4)
    {
        enforce(year.startsWith('-', '+'),
                new DateTimeException(format("Invalid string format: %s", simpleString)));
        enforce(all!isDigit(year[1..$]),
                new DateTimeException(format("Invalid string format: %s", simpleString)));
    }
    else
        enforce(all!isDigit(year),
                new DateTimeException(format("Invalid string format: %s", simpleString)));

    return Date(to!short(year), month, to!ubyte(day));
}

Date fromSimpleString2(S)(in S simpleString) @safe pure
    if (isSomeString!(S))
{
    import std.algorithm.searching : startsWith;
    import std.conv : to, ConvException;
    import std.format : format;
    import std.string : strip;

    auto str = strip(simpleString);

    if (str.length < 11 || str[$-3] != '-' || str[$-7] != '-')
        throw new DateTimeException(format!"Invalid string format: %s"(simpleString));

    short year;
    ubyte day;
    auto month = monthFromString(str[$ - 6 .. $ - 3]);
    auto yearStr = str[0 .. $ - 7];
    auto signAtBegining = cast(bool) yearStr.startsWith('-', '+');
    if ((yearStr.length > 4) != signAtBegining)
    {
        throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
    }

    try
    {
        day = to!ubyte(str[$ - 2 .. $]);
        year = to!short(yearStr);
    }
    catch (ConvException)
    {
        throw new DateTimeException(format!"Invalid string format: %s"(simpleString));
    }

    return Date(year, month, day);
}

Month monthFromString(T)(T monthStr) @safe pure
if (isSomeString!T)
{
    import std.format : format;
    switch (monthStr)
    {
        case "Jan":
            return Month.jan;
        case "Feb":
            return Month.feb;
        case "Mar":
            return Month.mar;
        case "Apr":
            return Month.apr;
        case "May":
            return Month.may;
        case "Jun":
            return Month.jun;
        case "Jul":
            return Month.jul;
        case "Aug":
            return Month.aug;
        case "Sep":
            return Month.sep;
        case "Oct":
            return Month.oct;
        case "Nov":
            return Month.nov;
        case "Dec":
            return Month.dec;
        default:
            throw new DateTimeException(format!"Invalid month %s"(monthStr));
    }
}

void main()
{
    auto result = to!Duration(benchmark!(() => fromSimpleString1("2010-Jul-04"))(testCount)[0]);
    auto result2 = to!Duration(benchmark!(() => fromSimpleString2("2010-Jul-04"))(testCount)[0]);

    writeln("old", "\t", result);
    writeln("new", "\t", result2);
}

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @JackStouffer!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

@JackStouffer JackStouffer force-pushed the date-fromSimpleString branch from e76a231 to 962db54 Compare January 25, 2018 17:30
@JackStouffer
Copy link
Contributor Author

Forgot that to!int/to!uint is slightly faster

@wilzbach
Copy link
Contributor

Once #6070 is merged, CircleCi can be restarted here.

@dlang-bot dlang-bot merged commit 80ee4b3 into dlang:master Jan 26, 2018
@JackStouffer JackStouffer deleted the date-fromSimpleString branch January 26, 2018 12:59
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.

4 participants