Source file src/cmd/internal/pgo/serialize.go

     1  // Copyright 2024 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 pgo
     6  
     7  import (
     8  	"bufio"
     9  	"fmt"
    10  	"io"
    11  )
    12  
    13  // Serialization of a Profile allows go tool preprofile to construct the edge
    14  // map only once (rather than once per compile process). The compiler processes
    15  // then parse the pre-processed data directly from the serialized format.
    16  //
    17  // The format of the serialized output is as follows.
    18  //
    19  //      GO PREPROFILE V1
    20  //      caller_name
    21  //      callee_name
    22  //      "call site offset" "call edge weight"
    23  //      ...
    24  //      caller_name
    25  //      callee_name
    26  //      "call site offset" "call edge weight"
    27  //
    28  // Entries are sorted by "call edge weight", from highest to lowest.
    29  
    30  const serializationHeader = "GO PREPROFILE V1\n"
    31  
    32  // WriteTo writes a serialized representation of Profile to w.
    33  //
    34  // FromSerialized can parse the format back to Profile.
    35  //
    36  // WriteTo implements io.WriterTo.Write.
    37  func (d *Profile) WriteTo(w io.Writer) (int64, error) {
    38  	bw := bufio.NewWriter(w)
    39  
    40  	var written int64
    41  
    42  	// Header
    43  	n, err := bw.WriteString(serializationHeader)
    44  	written += int64(n)
    45  	if err != nil {
    46  		return written, err
    47  	}
    48  
    49  	for _, edge := range d.NamedEdgeMap.ByWeight {
    50  		weight := d.NamedEdgeMap.Weight[edge]
    51  
    52  		n, err = fmt.Fprintln(bw, edge.CallerName)
    53  		written += int64(n)
    54  		if err != nil {
    55  			return written, err
    56  		}
    57  
    58  		n, err = fmt.Fprintln(bw, edge.CalleeName)
    59  		written += int64(n)
    60  		if err != nil {
    61  			return written, err
    62  		}
    63  
    64  		n, err = fmt.Fprintf(bw, "%d %d\n", edge.CallSiteOffset, weight)
    65  		written += int64(n)
    66  		if err != nil {
    67  			return written, err
    68  		}
    69  	}
    70  
    71  	if err := bw.Flush(); err != nil {
    72  		return written, err
    73  	}
    74  
    75  	// No need to serialize TotalWeight, it can be trivially recomputed
    76  	// during parsing.
    77  
    78  	return written, nil
    79  }
    80  

View as plain text