Code improvement for DNA reverse complement?

Biotronic via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun May 21 23:50:45 PDT 2017


On Friday, 19 May 2017 at 22:53:39 UTC, crimaniak wrote:
> On Friday, 19 May 2017 at 12:55:05 UTC, Biotronic wrote:
>> revComp6 seems to be the fastest, but it's probably also the 
>> least readable (a common trade-off).
> Try revComp7 with -release :)
>
> string revComp7(string bps)
> {
>     char[] result = new char[bps.length];
>     auto p1 = result.ptr;
>     auto p2 = &bps[$ - 1];
>     enum AT = 'A'^'T';
>     enum CG = 'C'^'G';
>
>     while (p2 > bps.ptr)
>     {
>        *p1 = *p2 ^ ((*p2 == 'A' || *p2 == 'T') ? AT : CG);
>         p1++;
>         p2--;
>     }
>     return result.assumeUnique;
> }
>
> In fact, when the size of the sequence is growing time 
> difference between procedures is shrinking, so it's much more 
> important to use memory-efficient presentation than to optimize 
> logic.

revComp7 is pretty fast, but I followed ag0aep6g's advice:

On Friday, 19 May 2017 at 13:38:20 UTC, ag0aep6g wrote:
> Use `static immutable` instead. It still forces compile-time 
> calculation, but it doesn't have copy/paste behavior. Speeds up 
> revComp3 a lot.

Also, with DMD (2.073.0) -release -O instead of -debug from this 
point. I'd blame someone else, but this is my fault. :p

Anyways, full collection of the various versions I've written, 
plus crimaniak's revComp7 (rebranded as revComp8, because I 
already had 7 at the time):

https://gist.github.com/Biotronic/20daaf0ed1262d313830bc8cd4199896

Timings:
revComp0:        158 ms, 926 us
revComp1: 1 sec, 157 ms,  15 us
revComp2:        604 ms,  37 us
revComp3:         18 ms, 545 us
revComp4:         92 ms, 293 us
revComp5:         86 ms, 731 us
revComp6:         94 ms,  56 us
revComp7:        917 ms, 576 us
revComp8:         62 ms, 917 us

This actually matches my expectations - the table lookup version 
should be crazy fast, and it is. It beats even your revComp7 
(revComp8 in the table).

LDC (-release -O3) timings:

revComp0: 166 ms, 190 us
revComp1: 352 ms, 917 us
revComp2: 300 ms, 493 us
revComp3:  10 ms, 950 us
revComp4: 148 ms, 106 us
revComp5: 144 ms, 152 us
revComp6: 142 ms, 307 us
revComp7: 604 ms, 274 us
revComp8:  26 ms, 612 us

Interesting how revComp4-6 got slower. What I really wanted to 
see with this though, was the effect on revComp1, which uses 
ranges all the way.


More information about the Digitalmars-d-learn mailing list