191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris/* 291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * Copyright 2013 The Android Open Source Project 391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * 491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * you may not use this file except in compliance with the License. 691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * You may obtain a copy of the License at 791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * 891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * 1091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * Unless required by applicable law or agreed to in writing, software 1191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 1291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * See the License for the specific language governing permissions and 1491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris * limitations under the License. 1591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris */ 1691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 1791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <stdio.h> 1891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <limits.h> 1991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <ctype.h> 2091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <unistd.h> 2191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 2291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <signal.h> 2391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <sys/types.h> 2491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <sys/stat.h> 2591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <fcntl.h> 2691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <dirent.h> 2791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 2891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <cutils/log.h> 2991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 3091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <algorithm> 3191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include <vector> 3291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 3391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#include "memtrack.h" 3491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 3591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#ifdef LOG_TAG 3691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#undef LOG_TAG 3791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#endif 3891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris#define LOG_TAG "MemTracker" 3991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 4091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher FerrisFileData::FileData(char *filename, char *buffer, size_t buffer_len) 4191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris : data_(buffer), max_(buffer_len), cur_idx_(0), len_(0), 4291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris read_complete_(false) { 4391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris fd_ = open(filename, O_RDONLY); 4491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (fd_ < 0) { 4591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris read_complete_ = true; 4691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 4791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 4891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 4991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher FerrisFileData::~FileData() { 5091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (fd_ >= 0) { 5191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris close(fd_); 5291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 5391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 5491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 5591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisbool FileData::isAvail(size_t bytes_needed) { 5691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (cur_idx_ + bytes_needed < len_) { 5791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return true; 5891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 5991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 6091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (read_complete_) { 6191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return false; 6291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 6391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 6491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (cur_idx_ != len_) { 6591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Copy the leftover to the front of the buffer. 6691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris len_ = len_ - cur_idx_; 6791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memcpy(data_, data_ + cur_idx_, len_); 6891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 6991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 7091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ssize_t bytes; 7191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_idx_ = 0; 7291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (cur_idx_ + bytes_needed >= len_) { 7391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris bytes = read(fd_, data_ + len_, max_ - len_); 7491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (bytes == 0 || bytes == -1) { 7591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris read_complete_; 7691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris break; 7791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 7891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris len_ += bytes; 7991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 8091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 8191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return cur_idx_ + bytes_needed < len_; 8291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 8391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 8491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisbool FileData::getPss(size_t *pss) { 8591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris size_t value; 8691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (true) { 8791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (!isAvail(4)) { 8891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return false; 8991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 9091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 9191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (data_[cur_idx_] != 'P' || data_[cur_idx_+1] != 's' || 9291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris data_[cur_idx_+2] != 's' || data_[cur_idx_+3] != ':') { 9391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Consume the rest of the line. 9491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (isAvail(1) && data_[cur_idx_++] != '\n'); 9591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } else { 9691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_idx_ += 4; 9791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (isAvail(1) && isspace(data_[cur_idx_])) { 9891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_idx_++; 9991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 10091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 10191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris value = 0; 10291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (isAvail(1) && isdigit(data_[cur_idx_])) { 10391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris value = value * 10 + data_[cur_idx_] - '0'; 10491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_idx_++; 10591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 10691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris *pss = value; 10791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 10891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Consume the rest of the line. 10991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (isAvail(1) && data_[cur_idx_++] != '\n'); 11091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 11191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return true; 11291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 11391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 11491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 11591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 11691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisconst char *ProcessInfo::kProc = "/proc/"; 11791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisconst char *ProcessInfo::kCmdline = "/cmdline"; 11891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisconst char *ProcessInfo::kSmaps = "/smaps"; 11991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 12091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher FerrisProcessInfo::ProcessInfo() { 12191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memcpy(proc_file_, kProc, kProcLen); 12291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 12391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 12491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher FerrisProcessInfo::~ProcessInfo() { 12591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 12691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 12791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisbool ProcessInfo::getInformation(int pid, char *pid_str, size_t pid_str_len) { 12891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memcpy(proc_file_ + kProcLen, pid_str, pid_str_len); 12991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memcpy(proc_file_ + kProcLen + pid_str_len, kCmdline, kCmdlineLen); 13091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 13191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Read the cmdline for the process. 13291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris int fd = open(proc_file_, O_RDONLY); 13391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (fd < 0) { 13491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return false; 13591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 13691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 13791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ssize_t bytes = read(fd, cmd_name_, sizeof(cmd_name_)); 13891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris close(fd); 13991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (bytes == -1 || bytes == 0) { 14091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return false; 14191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 14291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 14391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memcpy(proc_file_ + kProcLen + pid_str_len, kSmaps, kSmapsLen); 14491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris FileData smaps(proc_file_, buffer_, sizeof(buffer_)); 14591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 14691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_process_info_t process_info; 14791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris size_t pss_kb; 14891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris process_info.pss_kb = 0; 14991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (smaps.getPss(&pss_kb)) { 15091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris process_info.pss_kb += pss_kb; 15191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 15291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 15391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (cur_.count(cmd_name_) == 0) { 15491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_[cmd_name_] = process_info; 15591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } else { 15691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_[cmd_name_].pss_kb += process_info.pss_kb; 15791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 15891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_[cmd_name_].pids.push_back(pid); 15991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 16091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return true; 16191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 16291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 16391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisvoid ProcessInfo::scan() { 16491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris DIR *proc_dir = opendir(kProc); 16591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (proc_dir == NULL) { 16691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris perror("Cannot open directory.\n"); 16791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 16891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 16991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 17091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Clear any current pids. 17191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (processes_t::iterator it = all_.begin(); it != all_.end(); ++it) { 17291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris it->second.pids.clear(); 17391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 17491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 17591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris struct dirent *dir_data; 17691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris int len; 17791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris bool is_pid; 17891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris size_t pid; 17991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris cur_.clear(); 18091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while ((dir_data = readdir(proc_dir))) { 18191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Check if the directory entry represents a pid. 18291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris len = strlen(dir_data->d_name); 18391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris is_pid = true; 18491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris pid = 0; 18591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (int i = 0; i < len; i++) { 18691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (!isdigit(dir_data->d_name[i])) { 18791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris is_pid = false; 18891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris break; 18991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 19091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris pid = pid * 10 + dir_data->d_name[i] - '0'; 19191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 19291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (is_pid) { 19391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris getInformation(pid, dir_data->d_name, len); 19491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 19591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 19691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris closedir(proc_dir); 19791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 19891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Loop through the current processes and add them into our real list. 19991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (cur_processes_t::const_iterator it = cur_.begin(); 20091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris it != cur_.end(); ++it) { 20191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 20291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (all_.count(it->first) == 0) { 20391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Initialize all of the variables. 20491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].num_samples = 0; 20591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].name = it->first; 20691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].avg_pss_kb = 0; 20791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].min_pss_kb = 0; 20891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].max_pss_kb = 0; 20991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 21091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 21191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (it->second.pids.size() > all_[it->first].max_num_pids) { 21291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].max_num_pids = it->second.pids.size(); 21391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 21491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 21591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].pids = it->second.pids; 21691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 21791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (it->second.pss_kb > all_[it->first].max_pss_kb) { 21891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].max_pss_kb = it->second.pss_kb; 21991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 22091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 22191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (all_[it->first].min_pss_kb == 0 || 22291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris it->second.pss_kb < all_[it->first].min_pss_kb) { 22391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].min_pss_kb = it->second.pss_kb; 22491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 22591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 22691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].last_pss_kb = it->second.pss_kb; 22791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 22891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris computeAvg(&all_[it->first].avg_pss_kb, it->second.pss_kb, 22991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].num_samples); 23091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris all_[it->first].num_samples++; 23191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 23291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 23391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 23491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisbool comparePss(const process_info_t *first, const process_info_t *second) { 23591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris return first->max_pss_kb > second->max_pss_kb; 23691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 23791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 23891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisvoid ProcessInfo::dumpToLog() { 23991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris list_.clear(); 24091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (processes_t::const_iterator it = all_.begin(); it != all_.end(); ++it) { 24191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris list_.push_back(&it->second); 24291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 24391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 24491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Now sort the list. 24591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris std::sort(list_.begin(), list_.end(), comparePss); 24691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 24791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI("Dumping process list"); 24891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (std::vector<const process_info_t *>::const_iterator it = list_.begin(); 24991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris it != list_.end(); ++it) { 25091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Name: %s", (*it)->name.c_str()); 25191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Max running processes: %d", (*it)->max_num_pids); 25291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if ((*it)->pids.size() > 0) { 25391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Currently running pids:"); 25491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (std::vector<int>::const_iterator pid_it = (*it)->pids.begin(); 25591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris pid_it != (*it)->pids.end(); ++pid_it) { 25691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" %d", *pid_it); 25791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 25891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 25991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 26091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Min PSS %0.4fM", (*it)->min_pss_kb/1024.0); 26191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Avg PSS %0.4fM", (*it)->avg_pss_kb/1024.0); 26291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Max PSS %0.4fM", (*it)->max_pss_kb/1024.0); 26391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ALOGI(" Last PSS %0.4fM", (*it)->last_pss_kb/1024.0); 26491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 26591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 26691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 26791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisvoid usage() { 26891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Usage: memtrack [--verbose | --quiet] [--scan_delay TIME_SECS]\n"); 26991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" --scan_delay TIME_SECS\n"); 27091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" The amount of delay in seconds between scans.\n"); 27191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" --verbose\n"); 27291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" Print information about the scans to stdout only.\n"); 27391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" --quiet\n"); 27491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" Nothing will be printed to stdout.\n"); 27591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf(" All scan data is dumped to the android log using the tag %s\n", 27691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris LOG_TAG); 27791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 27891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 27991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisint SignalReceived = 0; 28091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 28191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisint SignalsToHandle[] = { 28291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SIGTSTP, 28391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SIGINT, 28491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SIGHUP, 28591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SIGPIPE, 28691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SIGUSR1, 28791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris}; 28891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 28991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisvoid handleSignal(int signo) { 29091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (SignalReceived == 0) { 29191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SignalReceived = signo; 29291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 29391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 29491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 29591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferrisint main(int argc, char **argv) { 29691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (geteuid() != 0) { 29791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Must be run as root.\n"); 29891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 29991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 30091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 30191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris bool verbose = false; 30291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris bool quiet = false; 30391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris unsigned int scan_delay_sec = DEFAULT_SLEEP_DELAY_SECONDS; 30491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (int i = 1; i < argc; i++) { 30591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (strcmp(argv[i], "--verbose") == 0) { 30691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris verbose = true; 30791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } else if (strcmp(argv[i], "--quiet") == 0) { 30891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris quiet = true; 30991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } else if (strcmp(argv[i], "--scan_delay") == 0) { 31091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (i+1 == argc) { 31191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("The %s options requires a single argument.\n", argv[i]); 31291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris usage(); 31391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 31491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 31591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris scan_delay_sec = atoi(argv[++i]); 31691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } else { 31791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Unknown option %s\n", argv[i]); 31891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris usage(); 31991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 32091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 32191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 32291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (quiet && verbose) { 32391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Both --quiet and --verbose cannot be specified.\n"); 32491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris usage(); 32591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 32691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 32791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 32891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris // Set up the signal handlers. 32991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris for (size_t i = 0; i < sizeof(SignalsToHandle)/sizeof(int); i++) { 33091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (signal(SignalsToHandle[i], handleSignal) == SIG_ERR) { 33191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Unable to handle signal %d\n", SignalsToHandle[i]); 33291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 33391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 33491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 33591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 33691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris ProcessInfo proc_info; 33791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 33891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (!quiet) { 33991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Hit Ctrl-Z or send SIGUSR1 to pid %d to print the current list of\n", 34091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris getpid()); 34191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("processes.\n"); 34291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Hit Ctrl-C to print the list of processes and terminate.\n"); 34391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 34491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 34591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris struct timespec t; 34691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris unsigned long long nsecs; 34791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris while (true) { 34891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (verbose) { 34991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memset(&t, 0, sizeof(t)); 35091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris clock_gettime(CLOCK_MONOTONIC, &t); 35191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris nsecs = (unsigned long long)t.tv_sec*NS_PER_SEC + t.tv_nsec; 35291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 35391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris proc_info.scan(); 35491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (verbose) { 35591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris memset(&t, 0, sizeof(t)); 35691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris clock_gettime(CLOCK_MONOTONIC, &t); 35791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris nsecs = ((unsigned long long)t.tv_sec*NS_PER_SEC + t.tv_nsec) - nsecs; 35891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Scan Time %0.4f\n", ((double)nsecs)/NS_PER_SEC); 35991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 36091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris 36191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (SignalReceived != 0) { 36291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris proc_info.dumpToLog(); 36391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (SignalReceived != SIGUSR1 && SignalReceived != SIGTSTP) { 36491f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris if (!quiet) { 36591f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris printf("Terminating...\n"); 36691f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 36791f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris exit(1); 36891f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 36991f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris SignalReceived = 0; 37091f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 37191f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris sleep(scan_delay_sec); 37291f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris } 37391f4410f49f8f701f9001c447b5bc6162c348f6bChristopher Ferris} 374