Source file test/bench/go1/revcomp_test.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This benchmark, taken from the shootout, tests array indexing
     6  // and array bounds elimination performance.
     7  
     8  package go1
     9  
    10  import (
    11  	"bufio"
    12  	"bytes"
    13  	"io"
    14  	"testing"
    15  )
    16  
    17  var revCompTable = [256]uint8{
    18  	'A': 'T', 'a': 'T',
    19  	'C': 'G', 'c': 'G',
    20  	'G': 'C', 'g': 'C',
    21  	'T': 'A', 't': 'A',
    22  	'U': 'A', 'u': 'A',
    23  	'M': 'K', 'm': 'K',
    24  	'R': 'Y', 'r': 'Y',
    25  	'W': 'W', 'w': 'W',
    26  	'S': 'S', 's': 'S',
    27  	'Y': 'R', 'y': 'R',
    28  	'K': 'M', 'k': 'M',
    29  	'V': 'B', 'v': 'B',
    30  	'H': 'D', 'h': 'D',
    31  	'D': 'H', 'd': 'H',
    32  	'B': 'V', 'b': 'V',
    33  	'N': 'N', 'n': 'N',
    34  }
    35  
    36  func revcomp(data []byte) {
    37  	in := bufio.NewReader(bytes.NewBuffer(data))
    38  	out := io.Discard
    39  	buf := make([]byte, 1024*1024)
    40  	line, err := in.ReadSlice('\n')
    41  	for err == nil {
    42  		out.Write(line)
    43  
    44  		// Accumulate reversed complement in buf[w:]
    45  		nchar := 0
    46  		w := len(buf)
    47  		for {
    48  			line, err = in.ReadSlice('\n')
    49  			if err != nil || line[0] == '>' {
    50  				break
    51  			}
    52  			line = line[0 : len(line)-1]
    53  			nchar += len(line)
    54  			if len(line)+nchar/60+128 >= w {
    55  				nbuf := make([]byte, len(buf)*5)
    56  				copy(nbuf[len(nbuf)-len(buf):], buf)
    57  				w += len(nbuf) - len(buf)
    58  				buf = nbuf
    59  			}
    60  
    61  			// This loop is the bottleneck.
    62  			for _, c := range line {
    63  				w--
    64  				buf[w] = revCompTable[c]
    65  			}
    66  		}
    67  
    68  		// Copy down to beginning of buffer, inserting newlines.
    69  		// The loop left room for the newlines and 128 bytes of padding.
    70  		i := 0
    71  		for j := w; j < len(buf); j += 60 {
    72  			n := copy(buf[i:i+60], buf[j:])
    73  			buf[i+n] = '\n'
    74  			i += n + 1
    75  		}
    76  		out.Write(buf[0:i])
    77  	}
    78  }
    79  
    80  func BenchmarkRevcomp(b *testing.B) {
    81  	b.SetBytes(int64(len(fastabytes)))
    82  	for i := 0; i < b.N; i++ {
    83  		revcomp(fastabytes)
    84  	}
    85  }
    86  

View as plain text