func()

in patches/gopsutil/v3/process/process_linux.go [380:481]


func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
	pid := p.Pid
	var ret []MemoryMapsStat
	smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps")
	if grouped {
		ret = make([]MemoryMapsStat, 1)
		// If smaps_rollup exists (require kernel >= 4.15), then we will use it
		// for pre-summed memory information for a process.
		smapsRollupPath := common.HostProc(strconv.Itoa(int(pid)), "smaps_rollup")
		if _, err := os.Stat(smapsRollupPath); !os.IsNotExist(err) {
			smapsPath = smapsRollupPath
		}
	}
	contents, err := ioutil.ReadFile(smapsPath)
	if err != nil {
		return nil, err
	}
	lines := strings.Split(string(contents), "\n")

	// function of parsing a block
	getBlock := func(firstLine []string, block []string) (MemoryMapsStat, error) {
		m := MemoryMapsStat{}
		m.Path = firstLine[len(firstLine)-1]

		for _, line := range block {
			if strings.Contains(line, "VmFlags") {
				continue
			}
			field := strings.Split(line, ":")
			if len(field) < 2 {
				continue
			}
			v := strings.Trim(field[1], "kB") // remove last "kB"
			v = strings.TrimSpace(v)
			t, err := strconv.ParseUint(v, 10, 64)
			if err != nil {
				return m, err
			}

			switch field[0] {
			case "Size":
				m.Size = t
			case "Rss":
				m.Rss = t
			case "Pss":
				m.Pss = t
			case "Shared_Clean":
				m.SharedClean = t
			case "Shared_Dirty":
				m.SharedDirty = t
			case "Private_Clean":
				m.PrivateClean = t
			case "Private_Dirty":
				m.PrivateDirty = t
			case "Referenced":
				m.Referenced = t
			case "Anonymous":
				m.Anonymous = t
			case "Swap":
				m.Swap = t
			}
		}
		return m, nil
	}

	var firstLine []string
	blocks := make([]string, 0, 16)

	for i, line := range lines {
		fields := strings.Fields(line)
		if (len(fields) > 0 && !strings.HasSuffix(fields[0], ":")) || i == len(lines)-1 {
			// new block section
			if len(firstLine) > 0 && len(blocks) > 0 {
				g, err := getBlock(firstLine, blocks)
				if err != nil {
					return &ret, err
				}
				if grouped {
					ret[0].Size += g.Size
					ret[0].Rss += g.Rss
					ret[0].Pss += g.Pss
					ret[0].SharedClean += g.SharedClean
					ret[0].SharedDirty += g.SharedDirty
					ret[0].PrivateClean += g.PrivateClean
					ret[0].PrivateDirty += g.PrivateDirty
					ret[0].Referenced += g.Referenced
					ret[0].Anonymous += g.Anonymous
					ret[0].Swap += g.Swap
				} else {
					ret = append(ret, g)
				}
			}
			// starts new block
			blocks = make([]string, 0, 16)
			firstLine = fields
		} else {
			blocks = append(blocks, line)
		}
	}

	return &ret, nil
}