sapling/eden/fs/utils/ProcUtil.h
Xavier Deguillard f4f159537f utils: add a platform independent FileUtils
Summary:
Up to now, Windows had to have its own version of folly::{readFile, writeFile,
writeFileAtomic} as these only operate on `char *` path, which can only
represent ascii paths on Windows. Since the Windows version is slightly
different from folly, this forced the code to either ifdef _WIN32, or use the
folly version pretending that it would be OK. The Windows version was also
behaving slightly differently from folly. For instance, where folly would
return a boolean to indicate success, on Windows we would throw an exception.

To simplify our code, add type safety and unify both, we can implement our own
wrappers on top of either folly or Windows APIs.

We still have some code that uses folly::readFile but these should only be
dealing with filedescriptors. As a following step, we may want to have our own
File class that wraps a file descriptor/HANDLE so we can completely remove all
uses of folly::readFile.

Reviewed By: wez

Differential Revision: D23037325

fbshipit-source-id: 2b9a026f3ee6220ef55097abe649b23e38d9fe91
2020-08-14 18:56:33 -07:00

126 lines
3.8 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#pragma once
#include <folly/Range.h>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
#include "eden/fs/utils/PathFuncs.h"
namespace facebook {
namespace eden {
constexpr folly::StringPiece kVmRSSKey{"VmRSS"};
constexpr folly::StringPiece kKBytes{"kB"};
constexpr folly::StringPiece kLinuxProcStatusPath{"/proc/self/status"};
constexpr folly::StringPiece kLinuxProcSmapsPath{"/proc/self/smaps"};
namespace proc_util {
struct MemoryStats {
/// Total VM Size, in bytes
size_t vsize = 0;
/// Resident set size, in bytes
size_t resident = 0;
/// Resident shared bytes (file mappings + shared memory)
/// Only available on Linux
std::optional<size_t> shared;
/// text (code) bytes
/// Only available on Linux
std::optional<size_t> text;
/// data + stack bytes
/// Only available on Linux
std::optional<size_t> data;
};
/**
* Read the memory stats for the current process.
*
* Returns std::nullopt if an error occurs reading or parsing the data.
*/
std::optional<MemoryStats> readMemoryStats();
/**
* Calculate the private bytes used by the eden process. The calculation
* is done by loading, parsing and summing values in /proc/self/smaps file.
* @return memory usage in bytes or 0 if the value could not be determined.
* On non-linux platforms, 0 will be returned.
*/
std::optional<size_t> calculatePrivateBytes();
#ifndef _WIN32
/**
* Read a /proc/<pid>/statm file and return the results as a MemoryStats object.
*
* Returns std::nullopt if an error occurs reading or parsing the data.
*/
std::optional<MemoryStats> readStatmFile(AbsolutePathPiece filename);
/**
* Parse the contents of a /proc/<pid>/statm file.
*/
std::optional<MemoryStats> parseStatmFile(
folly::StringPiece data,
size_t pageSize);
/**
* Trim leading and trailing delimiter characters from passed string.
* @return the modified string.
*/
std::string& trim(std::string& str, const std::string& delim = " \t\n\v\f\r");
/**
* Extract the key value pair form the passed line. The delimiter
* separates the key and value. Whitespace is trimmed from the result strings.
* @return key/value pair or two empty strings if number of segments != 2.
*/
std::pair<std::string, std::string> getKeyValuePair(
const std::string& line,
const std::string& delim);
/**
* Parse the passed stream (typically /proc/self/smaps).
* Callers should handle io exceptions (catch std::ios_base::failure).
* @return a list of maps for each entry.
*/
std::vector<std::unordered_map<std::string, std::string>> parseProcSmaps(
std::istream& input);
/**
* Load the contents of the linux proc/smaps from kLinuxProcSmapsPath.
* It handles file operations and exceptions. It makes use of
* parseProcSmaps for parsing file contents.
* @return a vector of maps with file contents or empty vector on error.
*/
std::vector<std::unordered_map<std::string, std::string>> loadProcSmaps();
/**
* Load the contents of the linux proc/smaps file from procSmapsPath.
* It handles file operations and exceptions. It makes use of
* parseProcSmaps for parsing file contents.
* It is provided to test loadProcSmaps.
* @return a vector of maps with file contents or empty vector on error.
*/
std::vector<std::unordered_map<std::string, std::string>> loadProcSmaps(
folly::StringPiece procSmapsPath);
/**
* Calculate the private byte count based on passed vector of maps.
* Intended for use by calculatePrivateBytes().
* @see parseProcSmaps to create the map.
*/
std::optional<size_t> calculatePrivateBytes(
std::vector<std::unordered_map<std::string, std::string>> smapsListOfMaps);
#endif
} // namespace proc_util
} // namespace eden
} // namespace facebook