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/ioutil" 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 := ioutil.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