github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/internal/traceparser/raw.go (about) 1 // Copyright 2018 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 package traceparser 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "hash/fnv" 11 "io" 12 "log" 13 ) 14 15 // convert batches into their raw events. For small intervals (1 or 10 seconds) 16 // this takes about 40% of the total Parse time. 17 18 func (p *Parsed) batchify(b *batch) error { 19 evs := make([]rawEvent, 0) 20 p.seenArgs = make(map[uint64]*[]uint64) 21 hasher := fnv.New64() 22 r := p.r 23 r.Seek(int64(b.Off), 0) 24 var buf [1]byte 25 seenBatch := false // to terminate the loop on the second EvBatch 26 27 for off := b.Off; ; { 28 off0 := off // remember the beginning of the event 29 n, err := r.Read(buf[:]) 30 if err != nil { 31 return err 32 } 33 off += n 34 typ := buf[0] << 2 >> 2 // event type is bottom 6 bits 35 if typ == EvFrequency || (typ == EvBatch && seenBatch) { 36 break // found trailer, or next batch 37 } 38 if typ == EvBatch { 39 seenBatch = true 40 } 41 if typ == EvString { 42 // skip over it. error checking was done in file.go 43 _, off, _ = readVal(r, off) 44 var ln uint64 45 ln, off, _ = readVal(r, off) 46 // PJW: why not just seek ahead ln bytes? 47 if false { 48 buf := make([]byte, ln) 49 var n int 50 n, _ = io.ReadFull(r, buf) 51 off += n 52 } else { 53 n, _ := r.Seek(int64(ln), 1) 54 off = int(n) 55 } 56 continue 57 } 58 // build the raw event and collect its arguments 59 ev := rawEvent{typ: typ, off: uint32(off0 - b.Off)} 60 var args []uint64 61 off, args, err = p.argsAt(off0, typ) 62 if err != nil { 63 // PJW: make sure this is useful 64 return fmt.Errorf("parsing %s failed at P=%d off=%d %v", evname(typ), 65 b.P, off0, err) 66 } 67 68 // have we seen the args before? 69 if len(args) > 0 { 70 ev.arg0 = args[0] 71 if len(args) > 1 { 72 hasher.Reset() 73 for i := 1; i < len(args); i++ { 74 var x [8]byte 75 binary.LittleEndian.PutUint64(x[:], args[i]) 76 _, err := hasher.Write(x[:]) 77 if err != nil { 78 log.Fatal(err) 79 } 80 } 81 hc := hasher.Sum64() 82 old, ok := p.seenArgs[hc] 83 if !ok { 84 final := make([]uint64, len(args)-1) 85 copy(final, args[1:]) 86 p.seenArgs[hc] = &final 87 } else { 88 // is this a collision? PJW: make this precisely right 89 if len(*old) != len(args[1:]) { 90 log.Fatalf("COLLISION old:%v this:%v", *old, args[1:]) 91 } 92 } 93 ev.args = p.seenArgs[hc] 94 } 95 } 96 if typ == EvUserLog { 97 // argsAt didn't read the string argument 98 var s string 99 s, off, err = readStr(r, off) 100 ev.sarg = s 101 } 102 evs = append(evs, ev) 103 } 104 b.raws = evs 105 return nil 106 }