|  | // Copyright 2011 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // This benchmark, taken from the shootout, tests array indexing | 
|  | // and array bounds elimination performance. | 
|  |  | 
|  | package go1 | 
|  |  | 
|  | import ( | 
|  | "bufio" | 
|  | "bytes" | 
|  | "io" | 
|  | "testing" | 
|  | ) | 
|  |  | 
|  | var revCompTable = [256]uint8{ | 
|  | 'A': 'T', 'a': 'T', | 
|  | 'C': 'G', 'c': 'G', | 
|  | 'G': 'C', 'g': 'C', | 
|  | 'T': 'A', 't': 'A', | 
|  | 'U': 'A', 'u': 'A', | 
|  | 'M': 'K', 'm': 'K', | 
|  | 'R': 'Y', 'r': 'Y', | 
|  | 'W': 'W', 'w': 'W', | 
|  | 'S': 'S', 's': 'S', | 
|  | 'Y': 'R', 'y': 'R', | 
|  | 'K': 'M', 'k': 'M', | 
|  | 'V': 'B', 'v': 'B', | 
|  | 'H': 'D', 'h': 'D', | 
|  | 'D': 'H', 'd': 'H', | 
|  | 'B': 'V', 'b': 'V', | 
|  | 'N': 'N', 'n': 'N', | 
|  | } | 
|  |  | 
|  | func revcomp(data []byte) { | 
|  | in := bufio.NewReader(bytes.NewBuffer(data)) | 
|  | out := io.Discard | 
|  | buf := make([]byte, 1024*1024) | 
|  | line, err := in.ReadSlice('\n') | 
|  | for err == nil { | 
|  | out.Write(line) | 
|  |  | 
|  | // Accumulate reversed complement in buf[w:] | 
|  | nchar := 0 | 
|  | w := len(buf) | 
|  | for { | 
|  | line, err = in.ReadSlice('\n') | 
|  | if err != nil || line[0] == '>' { | 
|  | break | 
|  | } | 
|  | line = line[0 : len(line)-1] | 
|  | nchar += len(line) | 
|  | if len(line)+nchar/60+128 >= w { | 
|  | nbuf := make([]byte, len(buf)*5) | 
|  | copy(nbuf[len(nbuf)-len(buf):], buf) | 
|  | w += len(nbuf) - len(buf) | 
|  | buf = nbuf | 
|  | } | 
|  |  | 
|  | // This loop is the bottleneck. | 
|  | for _, c := range line { | 
|  | w-- | 
|  | buf[w] = revCompTable[c] | 
|  | } | 
|  | } | 
|  |  | 
|  | // Copy down to beginning of buffer, inserting newlines. | 
|  | // The loop left room for the newlines and 128 bytes of padding. | 
|  | i := 0 | 
|  | for j := w; j < len(buf); j += 60 { | 
|  | n := copy(buf[i:i+60], buf[j:]) | 
|  | buf[i+n] = '\n' | 
|  | i += n + 1 | 
|  | } | 
|  | out.Write(buf[0:i]) | 
|  | } | 
|  | } | 
|  |  | 
|  | func BenchmarkRevcomp(b *testing.B) { | 
|  | bytes := makefasta() | 
|  | b.ResetTimer() | 
|  | b.SetBytes(int64(len(bytes))) | 
|  | for i := 0; i < b.N; i++ { | 
|  | revcomp(bytes) | 
|  | } | 
|  | } |