Functions
Aggregate
method
#
Aggregate merges the locations in the profile into equivalence
classes preserving the request attributes. It also updates the
samples to point to the merged locations.
func (p *Profile) Aggregate(inlineFrame bool, function bool, filename bool, linenumber bool, columnnumber bool, address bool) error
CheckValid
method
#
CheckValid tests whether the profile is valid. Checks include, but are
not limited to:
- len(Profile.Sample[n].value) == len(Profile.value_unit)
- Sample.id has a corresponding Profile.Location
func (p *Profile) CheckValid() error
Compact
method
#
Compact performs garbage collection on a profile to remove any
unreferenced fields. This is useful to reduce the size of a profile
after samples or locations have been removed.
func (p *Profile) Compact() *Profile
CompatibilizeSampleTypes
function
#
CompatibilizeSampleTypes makes profiles compatible to be compared/merged. It
keeps sample types that appear in all profiles only and drops/reorders the
sample types as necessary.
In the case of sample types order is not the same for given profiles the
order is derived from the first profile.
Profiles are modified in-place.
It returns an error if the sample type's intersection is empty.
func CompatibilizeSampleTypes(ps []*Profile) error
Copy
method
#
Copy makes a fully independent copy of a profile.
func (p *Profile) Copy() *Profile
DiffBaseSample
method
#
DiffBaseSample returns true if a sample belongs to the diff base and false
otherwise.
func (s *Sample) DiffBaseSample() bool
FilterSamplesByName
method
#
FilterSamplesByName filters the samples in a profile and only keeps
samples where at least one frame matches focus but none match ignore.
Returns true is the corresponding regexp matched at least one sample.
func (p *Profile) FilterSamplesByName(focus *regexp.Regexp, ignore *regexp.Regexp, hide *regexp.Regexp, show *regexp.Regexp) (fm bool, im bool, hm bool, hnm bool)
FilterSamplesByTag
method
#
FilterSamplesByTag removes all samples from the profile, except
those that match focus and do not match the ignore regular
expression.
func (p *Profile) FilterSamplesByTag(focus TagMatch, ignore TagMatch) (fm bool, im bool)
FilterTagsByName
method
#
FilterTagsByName filters the tags in a profile and only keeps
tags that match show and not hide.
func (p *Profile) FilterTagsByName(show *regexp.Regexp, hide *regexp.Regexp) (sm bool, hm bool)
HasFileLines
method
#
HasFileLines determines if all locations in this profile have
symbolized file and line number information.
func (p *Profile) HasFileLines() bool
HasFunctions
method
#
HasFunctions determines if all locations in this profile have
symbolized function information.
func (p *Profile) HasFunctions() bool
HasLabel
method
#
HasLabel returns true if a sample has a label with indicated key and value.
func (s *Sample) HasLabel(key string, value string) bool
Merge
function
#
Merge merges all the profiles in profs into a single Profile.
Returns a new profile independent of the input profiles. The merged
profile is compacted to eliminate unused samples, locations,
functions and mappings. Profiles must have identical profile sample
and period types or the merge will fail. profile.Period of the
resulting profile will be the maximum of all profiles, and
profile.TimeNanos will be the earliest nonzero one. Merges are
associative with the caveat of the first profile having some
specialization in how headers are combined. There may be other
subtleties now or in the future regarding associativity.
func Merge(srcs []*Profile) (*Profile, error)
Normalize
method
#
Normalize normalizes the source profile by multiplying each value in profile by the
ratio of the sum of the base profile's values of that sample type to the sum of the
source profile's value of that sample type.
func (p *Profile) Normalize(pb *Profile) error
NumLabelUnits
method
#
NumLabelUnits returns a map of numeric label keys to the units
associated with those keys and a map of those keys to any units
that were encountered but not used.
Unit for a given key is the first encountered unit for that key. If multiple
units are encountered for values paired with a particular key, then the first
unit encountered is used and all other units are returned in sorted order
in map of ignored units.
If no units are encountered for a particular key, the unit is then inferred
based on the key.
func (p *Profile) NumLabelUnits() (map[string]string, map[string][]string)
Parse
function
#
Parse parses a profile and checks for its validity. The input
may be a gzip-compressed encoded protobuf or one of many legacy
profile formats which may be unsupported in the future.
func Parse(r io.Reader) (*Profile, error)
ParseData
function
#
ParseData parses a profile from a buffer and checks for its
validity.
func ParseData(data []byte) (*Profile, error)
ParseMemoryMap
method
#
ParseMemoryMap parses a memory map in the format of
/proc/self/maps, and overrides the mappings in the current profile.
It renumbers the samples and locations in the profile correspondingly.
func (p *Profile) ParseMemoryMap(rd io.Reader) error
ParseMemoryMapFromScanner
method
#
ParseMemoryMapFromScanner parses a memory map in the format of
/proc/self/maps or a variety of legacy format, and overrides the
mappings in the current profile. It renumbers the samples and
locations in the profile correspondingly.
func (p *Profile) ParseMemoryMapFromScanner(s *bufio.Scanner) error
ParseProcMaps
function
#
ParseProcMaps parses a memory map in the format of /proc/self/maps.
ParseMemoryMap should be called after setting on a profile to
associate locations to the corresponding mapping based on their
address.
func ParseProcMaps(rd io.Reader) ([]*Mapping, error)
ParseUncompressed
function
#
ParseUncompressed parses an uncompressed protobuf into a profile.
func ParseUncompressed(data []byte) (*Profile, error)
Prune
method
#
Prune removes all nodes beneath a node matching dropRx, and not
matching keepRx. If the root node of a Sample matches, the sample
will have an empty stack.
func (p *Profile) Prune(dropRx *regexp.Regexp, keepRx *regexp.Regexp)
PruneFrom
method
#
PruneFrom removes all nodes beneath the lowest node matching dropRx, not including itself.
Please see the example below to understand this method as well as
the difference from Prune method.
A sample contains Location of [A,B,C,B,D] where D is the top frame and there's no inline.
PruneFrom(A) returns [A,B,C,B,D] because there's no node beneath A.
Prune(A, nil) returns [B,C,B,D] by removing A itself.
PruneFrom(B) returns [B,C,B,D] by removing all nodes beneath the first B when scanning from the bottom.
Prune(B, nil) returns [D] because a matching node is found by scanning from the root.
func (p *Profile) PruneFrom(dropRx *regexp.Regexp)
RemoveLabel
method
#
RemoveLabel removes all labels associated with the specified key for all
samples in the profile.
func (p *Profile) RemoveLabel(key string)
RemoveNumLabel
method
#
RemoveNumLabel removes all numerical labels associated with the specified key for all
samples in the profile.
func (p *Profile) RemoveNumLabel(key string)
RemoveUninteresting
method
#
RemoveUninteresting prunes and elides profiles using built-in
tables of uninteresting function names.
func (p *Profile) RemoveUninteresting() error
SampleIndexByName
method
#
SampleIndexByName returns the appropriate index for a value of sample index.
If numeric, it returns the number, otherwise it looks up the text in the
profile sample types.
func (p *Profile) SampleIndexByName(sampleIndex string) (int, error)
Scale
method
#
Scale multiplies all sample values in a profile by a constant and keeps
only samples that have at least one non-zero value.
func (p *Profile) Scale(ratio float64)
ScaleN
method
#
ScaleN multiplies each sample values in a sample by a different amount
and keeps only samples that have at least one non-zero value.
func (p *Profile) ScaleN(ratios []float64) error
SetLabel
method
#
SetLabel sets the specified key to the specified value for all samples in the
profile.
func (p *Profile) SetLabel(key string, value []string)
SetNumLabel
method
#
SetNumLabel sets the specified key to the specified value for all samples in the
profile. "unit" is a slice that describes the units that each corresponding member
of "values" is measured in (e.g. bytes or seconds). If there is no relevant
unit for a given value, that member of "unit" should be the empty string.
"unit" must either have the same length as "value", or be nil.
func (p *Profile) SetNumLabel(key string, value []int64, unit []string)
ShowFrom
method
#
ShowFrom drops all stack frames above the highest matching frame and returns
whether a match was found. If showFrom is nil it returns false and does not
modify the profile.
Example: consider a sample with frames [A, B, C, B], where A is the root.
ShowFrom(nil) returns false and has frames [A, B, C, B].
ShowFrom(A) returns true and has frames [A, B, C, B].
ShowFrom(B) returns true and has frames [B, C, B].
ShowFrom(C) returns true and has frames [C, B].
ShowFrom(D) returns false and drops the sample because no frames remain.
func (p *Profile) ShowFrom(showFrom *regexp.Regexp) (matched bool)
String
method
#
String dumps a text representation of a profile. Intended mainly
for debugging purposes.
func (p *Profile) String() string
Unsymbolizable
method
#
Unsymbolizable returns true if a mapping points to a binary for which
locations can't be symbolized in principle, at least now. Examples are
"[vdso]", "[vsyscall]" and some others, see the code.
func (m *Mapping) Unsymbolizable() bool
Write
method
#
Write writes the profile as a gzip-compressed marshaled protobuf.
func (p *Profile) Write(w io.Writer) error
WriteUncompressed
method
#
WriteUncompressed writes the profile as a marshaled protobuf.
func (p *Profile) WriteUncompressed(w io.Writer) error
addLegacyFrameInfo
method
#
func (p *Profile) addLegacyFrameInfo()
addString
function
#
func addString(strings map[string]int, s string) int64
adjacent
function
#
adjacent returns whether two mapping entries represent the same
mapping that has been split into two. Check that their addresses are adjacent,
and if the offsets match, if they are available.
func adjacent(m1 *Mapping, m2 *Mapping) bool
checkType
function
#
func checkType(b *buffer, typ int) error
cleanupDuplicateLocations
function
#
func cleanupDuplicateLocations(p *Profile)
commonSampleTypes
function
#
commonSampleTypes returns sample types that appear in all profiles in the
order how they ordered in the first profile.
func commonSampleTypes(ps []*Profile) []string
compatibilizeSampleTypes
function
#
compatibilizeSampleTypes drops sample types that are not present in sTypes
list and reorder them if needed.
It sets DefaultSampleType to sType[0] if it is not in sType list.
It assumes that all sample types from the sTypes list are present in the
given profile otherwise it returns an error.
func compatibilizeSampleTypes(p *Profile, sTypes []string) error
compatible
method
#
compatible determines if two profiles can be compared/merged.
returns nil if the profiles are compatible; otherwise an error with
details on the incompatibility.
func (p *Profile) compatible(pb *Profile) error
cpuProfile
function
#
cpuProfile returns a new Profile from C++ profilez data.
b is the profile bytes after the header, period is the profiling
period, and parse is a function to parse 8-byte chunks from the
profile in its native endianness.
func cpuProfile(b []byte, period int64, parse func(b []byte) (uint64, []byte)) (*Profile, error)
decodeBool
function
#
func decodeBool(b *buffer, x *bool) error
decodeField
function
#
func decodeField(b *buffer, data []byte) ([]byte, error)
decodeInt64
function
#
func decodeInt64(b *buffer, x *int64) error
decodeInt64s
function
#
func decodeInt64s(b *buffer, x *[]int64) error
decodeMessage
function
#
func decodeMessage(b *buffer, m message) error
decodeString
function
#
func decodeString(b *buffer, x *string) error
decodeStrings
function
#
func decodeStrings(b *buffer, x *[]string) error
decodeUint64
function
#
func decodeUint64(b *buffer, x *uint64) error
decodeUint64s
function
#
func decodeUint64s(b *buffer, x *[]uint64) error
decodeVarint
function
#
func decodeVarint(data []byte) (uint64, []byte, error)
decoder
method
#
func (p *Profile) decoder() []decoder
decoder
method
#
func (p *Sample) decoder() []decoder
decoder
method
#
func (p *Function) decoder() []decoder
decoder
method
#
func (p *Mapping) decoder() []decoder
decoder
method
#
func (p *Location) decoder() []decoder
decoder
method
#
func (p *Line) decoder() []decoder
decoder
method
#
func (p *ValueType) decoder() []decoder
decoder
method
#
func (p label) decoder() []decoder
encode
method
#
func (p *Location) encode(b *buffer)
encode
method
#
func (p *Mapping) encode(b *buffer)
encode
method
#
func (p *Sample) encode(b *buffer)
encode
method
#
func (p *ValueType) encode(b *buffer)
encode
method
#
func (p *Line) encode(b *buffer)
encode
method
#
func (p label) encode(b *buffer)
encode
method
#
func (p *Function) encode(b *buffer)
encode
method
#
func (p *Profile) encode(b *buffer)
encodeBool
function
#
func encodeBool(b *buffer, tag int, x bool)
encodeBoolOpt
function
#
func encodeBoolOpt(b *buffer, tag int, x bool)
encodeInt64
function
#
func encodeInt64(b *buffer, tag int, x int64)
encodeInt64Opt
function
#
func encodeInt64Opt(b *buffer, tag int, x int64)
encodeInt64s
function
#
func encodeInt64s(b *buffer, tag int, x []int64)
encodeLength
function
#
func encodeLength(b *buffer, tag int, len int)
encodeMessage
function
#
func encodeMessage(b *buffer, tag int, m message)
encodeString
function
#
func encodeString(b *buffer, tag int, x string)
encodeStrings
function
#
func encodeStrings(b *buffer, tag int, x []string)
encodeUint64
function
#
func encodeUint64(b *buffer, tag int, x uint64)
encodeUint64Opt
function
#
func encodeUint64Opt(b *buffer, tag int, x uint64)
encodeUint64s
function
#
func encodeUint64s(b *buffer, tag int, x []uint64)
encodeVarint
function
#
func encodeVarint(b *buffer, x uint64)
equalValueType
function
#
equalValueType returns true if the two value types are semantically
equal. It ignores the internal fields used during encode/decode.
func equalValueType(st1 *ValueType, st2 *ValueType) bool
filterShowFromLocation
function
#
filterShowFromLocation tests a showFrom regex against a location, removes
lines after the last match and returns whether a match was found. If the
mapping is matched, then all lines are kept.
func filterShowFromLocation(loc *Location, showFrom *regexp.Regexp) bool
focusedAndNotIgnored
function
#
focusedAndNotIgnored looks up a slice of ids against a map of
focused/ignored locations. The map only contains locations that are
explicitly focused or ignored. Returns whether there is at least
one focused location but no ignored locations.
func focusedAndNotIgnored(locs []*Location, m map[uint64]bool) bool
get
method
#
func (lm locationIDMap) get(id uint64) *Location
get32b
function
#
func get32b(b []byte) (uint64, []byte)
get32l
function
#
func get32l(b []byte) (uint64, []byte)
get64b
function
#
func get64b(b []byte) (uint64, []byte)
get64l
function
#
func get64l(b []byte) (uint64, []byte)
getString
function
#
func getString(strings []string, strng *int64, err error) (string, error)
isMemoryMapSentinel
function
#
isMemoryMapSentinel returns true if the string contains one of the
known sentinels for memory map information.
func isMemoryMapSentinel(line string) bool
isProfileType
function
#
func isProfileType(p *Profile, types [][]string) bool
isZeroSample
function
#
func isZeroSample(s *Sample) bool
javaCPUProfile
function
#
javaCPUProfile returns a new Profile from profilez data.
b is the profile bytes after the header, period is the profiling
period, and parse is a function to parse 8-byte chunks from the
profile in its native endianness.
func javaCPUProfile(b []byte, period int64, parse func(b []byte) (uint64, []byte)) (*Profile, error)
key
method
#
key generates encoded strings of Mapping to be used as a key for
maps.
func (m *Mapping) key() mappingKey
key
method
#
key generates a struct to be used as a key for maps.
func (f *Function) key() functionKey
key
method
#
key generates locationKey to be used as a key for maps.
func (l *Location) key() locationKey
labelsToString
function
#
labelsToString returns a string representation of a
map representing labels.
func labelsToString(labels map[string][]string) string
lastMatchedLineIndex
method
#
lastMatchedLineIndex returns the index of the last line that matches a regex,
or -1 if no match is found.
func (loc *Location) lastMatchedLineIndex(re *regexp.Regexp) int
le32
function
#
func le32(p []byte) uint32
le64
function
#
func le64(p []byte) uint64
makeLocationIDMap
function
#
func makeLocationIDMap(n int) locationIDMap
mapFunction
method
#
func (pm *profileMerger) mapFunction(src *Function) *Function
mapLine
method
#
func (pm *profileMerger) mapLine(src Line) Line
mapLocation
method
#
func (pm *profileMerger) mapLocation(src *Location) *Location
mapMapping
method
#
func (pm *profileMerger) mapMapping(src *Mapping) mapInfo
mapSample
method
#
func (pm *profileMerger) mapSample(src *Sample) *Sample
marshal
function
#
func marshal(m message) []byte
massageMappings
method
#
massageMappings applies heuristic-based changes to the profile
mappings to account for quirks of some environments.
func (p *Profile) massageMappings()
matchedLines
method
#
matchedLines returns the lines in the location that match
the regular expression.
func (loc *Location) matchedLines(re *regexp.Regexp) []Line
matchesName
method
#
matchesName returns whether the location matches the regular
expression. It checks any available function names, file names, and
mapping object filename.
func (loc *Location) matchesName(re *regexp.Regexp) bool
numLabelsToString
function
#
numLabelsToString returns a string representation of a map
representing numeric labels.
func numLabelsToString(numLabels map[string][]int64, numUnits map[string][]string) string
padStringArray
function
#
padStringArray pads arr with enough empty strings to make arr
length l when arr's length is less than l.
func padStringArray(arr []string, l int) []string
parseAdditionalSections
function
#
parseAdditionalSections parses any additional sections in the
profile, ignoring any unrecognized sections.
func parseAdditionalSections(s *bufio.Scanner, p *Profile) error
parseCPU
function
#
parseCPU parses a profilez legacy profile and returns a newly
populated Profile.
The general format for profilez samples is a sequence of words in
binary format. The first words are a header with the following data:
1st word -- 0
2nd word -- 3
3rd word -- 0 if a c++ application, 1 if a java application.
4th word -- Sampling period (in microseconds).
5th word -- Padding.
func parseCPU(b []byte) (*Profile, error)
parseCPUSamples
function
#
parseCPUSamples parses a collection of profilez samples from a
profile.
profilez samples are a repeated sequence of stack frames of the
form:
1st word -- The number of times this stack was encountered.
2nd word -- The size of the stack (StackSize).
3rd word -- The first address on the stack.
...
StackSize + 2 -- The last address on the stack
The last stack trace is of the form:
1st word -- 0
2nd word -- 1
3rd word -- 0
Addresses from stack traces may point to the next instruction after
each call. Optionally adjust by -1 to land somewhere on the actual
call (except for the leaf, which is not a call).
func parseCPUSamples(b []byte, parse func(b []byte) (uint64, []byte), adjust bool, p *Profile) ([]byte, map[uint64]*Location, error)
parseContention
function
#
parseContention parses a mutex or contention profile. There are 2 cases:
"--- contentionz " for legacy C++ profiles (and backwards compatibility)
"--- mutex:" or "--- contention:" for profiles generated by the Go runtime.
func parseContention(b []byte) (*Profile, error)
parseContentionSample
function
#
parseContentionSample parses a single row from a contention profile
into a new Sample.
func parseContentionSample(line string, period int64, cpuHz int64) (value []int64, addrs []uint64, err error)
parseGoCount
function
#
parseGoCount parses a Go count profile (e.g., threadcreate or
goroutine) and returns a new Profile.
func parseGoCount(b []byte) (*Profile, error)
parseHeap
function
#
parseHeap parses a heapz legacy or a growthz profile and
returns a newly populated Profile.
func parseHeap(b []byte) (p *Profile, err error)
parseHeapSample
function
#
parseHeapSample parses a single row from a heap profile into a new Sample.
func parseHeapSample(line string, rate int64, sampling string, includeAlloc bool) (value []int64, blocksize int64, addrs []uint64, err error)
parseHexAddresses
function
#
parseHexAddresses extracts hex numbers from a string, attempts to convert
each to an unsigned 64-bit number and returns the resulting numbers as a
slice, or an error if the string contains hex numbers which are too large to
handle (which means a malformed profile).
func parseHexAddresses(s string) ([]uint64, error)
parseJavaLocations
function
#
parseJavaLocations parses the location information in a java
profile and populates the Locations in a profile. It uses the
location addresses from the profile as both the ID of each
location.
func parseJavaLocations(b []byte, locs map[uint64]*Location, p *Profile) error
parseJavaProfile
function
#
parseJavaProfile returns a new profile from heapz or contentionz
data. b is the profile bytes after the header.
func parseJavaProfile(b []byte) (*Profile, error)
parseJavaSamples
function
#
parseJavaSamples parses the samples from a java profile and
populates the Samples in a profile. Returns the remainder of the
buffer after the samples.
func parseJavaSamples(pType string, b []byte, p *Profile) ([]byte, map[uint64]*Location, error)
parseLegacy
function
#
func parseLegacy(data []byte) (*Profile, error)
parseMappingEntry
function
#
func parseMappingEntry(l string) (*Mapping, error)
parseProcMapsFromScanner
function
#
func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error)
parseThread
function
#
parseThread parses a Threadz profile and returns a new Profile.
func parseThread(b []byte) (*Profile, error)
parseThreadSample
function
#
parseThreadSample parses a symbolized or unsymbolized stack trace.
Returns the first line after the traceback, the sample (or nil if
it hits a 'same-as-previous' marker) and an error.
func parseThreadSample(s *bufio.Scanner) (nextl string, addrs []uint64, err error)
postDecode
method
#
postDecode takes the unexported fields populated by decode (with
suffix X) and populates the corresponding exported fields.
The unexported fields are cleared up to facilitate testing.
func (p *Profile) postDecode() error
preEncode
method
#
preEncode populates the unexported fields to be used by encode
(with suffix X) from the corresponding exported fields. The
exported fields are cleared up to facilitate testing.
func (p *Profile) preEncode()
remapFunctionIDs
method
#
func (p *Profile) remapFunctionIDs()
remapLocationIDs
method
#
remapLocationIDs ensures there is a location for each address
referenced by a sample, and remaps the samples to point to the new
location ids.
func (p *Profile) remapLocationIDs()
remapMappingIDs
method
#
remapMappingIDs matches location addresses with existing mappings
and updates them appropriately. This is O(N*M), if this ever shows
up as a bottleneck, evaluate sorting the mappings and doing a
binary search, which would make it O(N*log(M)).
func (p *Profile) remapMappingIDs()
removeLoggingInfo
function
#
removeLoggingInfo detects and removes log prefix entries generated
by the glog package. If no logging prefix is detected, the string
is returned unmodified.
func removeLoggingInfo(line string) string
sampleKey
method
#
func (pm *profileMerger) sampleKey(sample *Sample) sampleKey
sampleTypes
function
#
func sampleTypes(p *Profile) []string
scaleHeapSample
function
#
scaleHeapSample adjusts the data from a heapz Sample to
account for its probability of appearing in the collected
data. heapz profiles are a sampling of the memory allocations
requests in a program. We estimate the unsampled value by dividing
each collected sample by its probability of appearing in the
profile. heapz v2 profiles rely on a poisson process to determine
which samples to collect, based on the desired average collection
rate R. The probability of a sample of size S to appear in that
profile is 1-exp(-S/R).
func scaleHeapSample(count int64, size int64, rate int64) (int64, int64)
searchValueType
function
#
func searchValueType(vts []*ValueType, s string) int
serialize
function
#
func serialize(p *Profile) []byte
set
method
#
func (lm locationIDMap) set(id uint64, loc *Location)
simplifyFunc
function
#
simplifyFunc does some primitive simplification of function names.
func simplifyFunc(f string) string
sortedKeys1
function
#
sortedKeys1 returns the sorted keys found in a string->[]string map.
Note: this is currently non-generic since github pprof runs golint,
which does not support generics. When that issue is fixed, it can
be merged with sortedKeys2 and made into a generic function.
func sortedKeys1(m map[string][]string) []string
sortedKeys2
function
#
sortedKeys2 returns the sorted keys found in a string->[]int64 map.
Note: this is currently non-generic since github pprof runs golint,
which does not support generics. When that issue is fixed, it can
be merged with sortedKeys1 and made into a generic function.
func sortedKeys2(m map[string][]int64) []string
string
method
#
string dumps a text representation of a location. Intended mainly
for debugging purposes.
func (l *Location) string() string
string
method
#
string dumps a text representation of a mapping. Intended mainly
for debugging purposes.
func (m *Mapping) string() string
string
method
#
string dumps a text representation of a sample. Intended mainly
for debugging purposes.
func (s *Sample) string() string
unmarshal
function
#
func unmarshal(data []byte, m message) (err error)
unmatchedLines
method
#
unmatchedLines returns the lines in the location that do not match
the regular expression.
func (loc *Location) unmatchedLines(re *regexp.Regexp) []Line
updateLocationMapping
method
#
func (p *Profile) updateLocationMapping(from *Mapping, to *Mapping)