faster splitter

qznc via Digitalmars-d digitalmars-d at puremagic.com
Sun May 22 11:56:30 PDT 2016


On Monday, 4 March 2013 at 19:11:17 UTC, Steven Schveighoffer 
wrote:
> On Mon, 04 Mar 2013 12:35:23 -0500, Andrei Alexandrescu 
> <SeeWebsiteForEmail at erdani.org> wrote:
>
>> That's comparable, please file an enh request.
>
> http://d.puremagic.com/issues/show_bug.cgi?id=9646


Below is an implementation, which matches MySplitter with dmd, 
but not with ldc. More precisely:

dmd -O -release -inline -noboundscheck:
std.algorithm.splitter took 5 secs, 170 ms, and 656 μs
MySplitter took 4 secs, 835 ms, 748 μs, and 1 hnsec
my_splitter took 4 secs, 862 ms, 914 μs, and 4 hnsecs

ldc2 -O -release:
std.algorithm.splitter took 3 secs, 540 ms, and 84 μs
MySplitter took 2 secs, 288 ms, and 535 μs
my_splitter took 3 secs, 463 ms, and 897 μs

CPU: Intel i7 M 620 2.67GHz
dmd: v2.070.2
ldc: 0.17.1 (based on DMD v2.068.2 and LLVM 3.7.1)

auto my_splitter(alias pred = "a == b", Range, Separator)(Range 
r, Separator s)
if (is(typeof(binaryFun!pred(r.front, s.front)) : bool)
         && (hasSlicing!Range || isNarrowString!Range)
         && isForwardRange!Separator
         && (hasLength!Separator || isNarrowString!Separator))
{
     import std.algorithm.searching : find;
     import std.conv : unsigned;

     static struct Result
     {
     private:
         Range _input;
         Separator _separator;
         size_t _next_index;
         bool _empty;

         @property auto separatorLength() { return 
_separator.length; }

         void findIndex()
         {
             auto found = find!pred(_input, _separator);
             _next_index = _input.length - found.length;
         }

     public:
         this(Range input, Separator separator)
         {
             _input = input;
             _separator = separator;
             _empty = false;
             findIndex();
         }

         @property Range front()
         {
             assert(!empty);
             return _input[0 .. _next_index];
         }

         static if (isInfinite!Range)
         {
             enum bool empty = false;  // Propagate infiniteness
         }
         else
         {
             @property bool empty()
             {
                 return _empty;
             }
         }

         void popFront()
         {
             assert(!empty);
             if (_input.empty) {
                 _empty = true;
                 assert(_next_index == 0);
             } else if (_input.length == _next_index) {
                 _input = _input[$ .. $];
                 _empty = true;
             } else {
                 _input = _input[_next_index + separatorLength .. 
$];
                 findIndex();
             }
         }

         static if (isForwardRange!Range)
         {
             @property typeof(this) save()
             {
                 auto ret = this;
                 ret._input = _input.save;
                 return ret;
             }
         }
     }

     return Result(r, s);
}



More information about the Digitalmars-d mailing list