Copyright 2018 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

package profiler

import (
	
	
	
	
	

	
)
heapProfile collects an in-use heap profile. The heap profiles returned by the runtime also include the heap allocation metrics. We zero those out since all allocations since program start are recorded, so these make the profile large and there is a separate alloc profile type which shows allocations from a set duration.
func ( *bytes.Buffer) error {
	,  := goHeapProfile()
	if  != nil {
		return 
	}
	for ,  := range .Sample {
		.Value[0] = 0
		.Value[1] = 0
	}
Merge profile with itself to remove samples with only zero values and reduce profile size.
	,  = profile.Merge([]*profile.Profile{})
	if  != nil {
		return 
	}
	return .Write()
}
deltaAllocProfile collects an allocation profile by gathering a heap profile, sleeping for the specified duration, gathering another heap profile and subtracting the initial one from that. It then drops the in-use metrics from the profile. If requested, it forces the GC before taking each of the heap profiles, which improves the profile accuracy (see docs in https://golang.org/src/runtime/mprof.go on why).
func ( context.Context,  time.Duration,  bool,  *bytes.Buffer) error {
	,  := allocProfile()
	if  != nil {
		return 
	}

	sleep(, )

	,  := allocProfile()
	if  != nil {
		return 
	}

	.Scale(-1)
	,  := profile.Merge([]*profile.Profile{, })
	if  != nil {
		return 
	}
	.DurationNanos = .Nanoseconds()
	return .Write()
}
allocProfile collects a single heap profile, and removes all metrics but allocation metrics.
func ( bool) (*profile.Profile, error) {
	if  {
		runtime.GC()
	}
	,  := goHeapProfile()
	if  != nil {
		return nil, 
	}
	.SampleType = .SampleType[:2]
	for ,  := range .Sample {
		.Value = .Value[:2]
	}
	return , nil
}
goHeapProfile collects a heap profile. It returns an error if the metrics in the collected heap profile do not match the expected metrics.
func () (*profile.Profile, error) {
	var  bytes.Buffer
	if  := writeHeapProfile(&);  != nil {
		return nil, fmt.Errorf("failed to write heap profile: %v", )
	}
	,  := profile.Parse(&)
	if  != nil {
		return nil, 
	}
	if  := len(.SampleType);  != 4 {
		return nil, fmt.Errorf("invalid heap profile: got %d sample types, want 4", )
	}
	for ,  := range []string{"alloc_objects", "alloc_space", "inuse_objects", "inuse_space"} {
		if  := .SampleType[].Type;  !=  {
			return nil, fmt.Errorf("invalid heap profile: got %q sample type at index %d, want %q", , , )
		}
	}
	return , nil