Skip to content

Commit

Permalink
fix: 系统监视器占用资源过高优化
Browse files Browse the repository at this point in the history
系统监视器占用资源过高优化

Log: 系统监视器占用资源过高优化
  • Loading branch information
jeffshuai authored and deepin-bot[bot] committed Aug 1, 2023
1 parent 9b35444 commit 9aaa92d
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 32 deletions.
2 changes: 1 addition & 1 deletion deepin-system-monitor-main/compact_memory_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ CompactMemoryMonitor::CompactMemoryMonitor(QWidget *parent)
changeTheme(dAppHelper->themeType());

m_animation = new QPropertyAnimation(this, "progress", this);
m_animation->setDuration(250);
m_animation->setDuration(10);
m_animation->setEasingCurve(QEasingCurve::OutQuad);
m_animation->setStartValue(0);
m_animation->setEndValue(1.0);
Expand Down
2 changes: 1 addition & 1 deletion deepin-system-monitor-main/cpu_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ CpuMonitor::CpuMonitor(QWidget *parent)
connect(m_cpuInfomodel, &CPUInfoModel::modelUpdated, this, &CpuMonitor::updateStatus);

m_animation = new QPropertyAnimation(this, "progress", this);
m_animation->setDuration(250);
m_animation->setDuration(20);
m_animation->setStartValue(0.0);
m_animation->setEndValue(1.0);
m_animation->setEasingCurve(QEasingCurve::OutQuad);
Expand Down
2 changes: 1 addition & 1 deletion deepin-system-monitor-main/gui/animation_stackedwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ AnimationStackedWidget::AnimationStackedWidget(const AnimationOri ori, QWidget *
, m_animationOri(ori)
, m_Animation(new QPropertyAnimation(this, "offset"))
{
setDuration(250);
setDuration(20);
connect(m_Animation
, &QPropertyAnimation::finished
, this
Expand Down
2 changes: 1 addition & 1 deletion deepin-system-monitor-main/gui/animation_stackedwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AnimationStackedWidget : public QStackedWidget
* @brief setDuration 设置动画持续时间
* @param duration 动画时间
*/
void setDuration(int duration = 500);
void setDuration(int duration = 10);
/**
* @brief IsRunning 动画是否正在运行
* @return 动画师傅正在运行
Expand Down
2 changes: 1 addition & 1 deletion deepin-system-monitor-main/memory_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ MemoryMonitor::MemoryMonitor(QWidget *parent)
m_animation = new QPropertyAnimation(this, "progress", this);
m_animation->setStartValue(0.0);
m_animation->setEndValue(1.0);
m_animation->setDuration(250);
m_animation->setDuration(10);
connect(m_animation, &QPropertyAnimation::valueChanged, this, &MemoryMonitor::onValueChanged);
connect(m_animation, &QPropertyAnimation::finished, this, &MemoryMonitor::onAnimationFinished);

Expand Down
101 changes: 98 additions & 3 deletions deepin-system-monitor-main/process/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,92 @@ timeval Process::procuptime() const
return d->uptime;
}

void Process::readProcessVariableInfo()
{
d->valid = true;

bool ok = true;
ok = ok && readStat();
// readEnviron();
readSchedStat();
ok = ok && readStatm();

readIO();
readSockInodes();

d->proc_name.refreashProcessName(this);
d->uptime = SysInfo::instance()->uptime();

CPUSet *cpuset = DeviceDB::instance()->cpuSet();
ProcessSet *procset = ProcessDB::instance()->processSet();

auto recentProcptr = procset->getRecentProcStage(d->pid);
auto validrecentPtr = recentProcptr.lock();
qreal timedelta = d->stime + d->utime;
if (validrecentPtr) {
timedelta = timedelta - validrecentPtr->ptime;
struct DiskIO io = {validrecentPtr->read_bytes, validrecentPtr->write_bytes, validrecentPtr->cancelled_write_bytes};
d->diskIOSample->addSample(new DISKIOSampleFrame(validrecentPtr->uptime, io));

d->networkIOSample->addSample(new IOSampleFrame(validrecentPtr->uptime, {0, 0}));
}
d->cpuUsageSample->addSample(new CPUUsageSampleFrame(qMax(0., timedelta) / cpuset->getUsageTotalDelta() * 100));

struct DiskIO io = {d->read_bytes, d->write_bytes, d->cancelled_write_bytes};
d->diskIOSample->addSample(new DISKIOSampleFrame(d->uptime, io));

auto pair = d->diskIOSample->recentSamplePair();
struct IOPS iops = DISKIOSampleFrame::diskiops(pair.first, pair.second);
d->diskIOSpeedSample->addSample(new IOPSSampleFrame(iops));

qulonglong sum_recv = 0;
qulonglong sum_send = 0;

for (int i = 0; i < d->sockInodes.size(); ++i) {
SockIOStat sockIOStat;
bool result = NetifMonitor::instance()->getSockIOStatByInode(d->sockInodes[i], sockIOStat);
if (result) {
sum_recv += sockIOStat->rx_bytes;
sum_send += sockIOStat->tx_bytes;
}
}
d->networkIOSample->addSample(new IOSampleFrame(d->uptime, {sum_recv, sum_send}));

auto netpair = d->networkIOSample->recentSamplePair();
struct IOPS netiops = IOSampleFrame::iops(netpair.first, netpair.second);
d->networkBandwidthSample->addSample(new IOPSSampleFrame(netiops));

d->valid = d->valid && ok;
}

void Process::readProcessSimpleInfo()
{
d->valid = true;
bool ok = true;
readEnviron();
ok = ok && readStat();
ok = ok && readStatus();
ok = ok && readCmdline();

d->usrerName = SysInfo::userName(d->uid);
d->proc_name.refreashProcessName(this);
d->proc_icon.refreashProcessIcon(this);

d->apptype = kNoFilter;
const QVariant &euid = ProcessDB::instance()->processEuid();
WMWindowList *wmwindowList = ProcessDB::instance()->windowList();

if (euid == d->uid && (wmwindowList->isGuiApp(d->pid)
|| wmwindowList->isTrayApp(d->pid)
|| wmwindowList->isDesktopEntryApp(d->pid))) {
d->apptype = kFilterApps;
} else if (euid == d->uid) {
d->apptype = kFilterCurrentUser;
}

d->valid = d->valid && ok;
}

void Process::readProcessInfo()
{
d->valid = true;
Expand Down Expand Up @@ -207,6 +293,8 @@ bool Process::readStat()

errno = 0;
sprintf(path, PROC_STAT_PATH, d->pid);
if(access(path, R_OK) != 0) return !ok; /* no such dirent (anymore) */

// open /proc/[pid]/stat
if ((fd = open(path, O_RDONLY)) < 0) {
print_errno(errno, QString("open %1 failed").arg(path));
Expand Down Expand Up @@ -281,6 +369,7 @@ bool Process::readCmdline()
char *begin, *cur, *end;

sprintf(path, PROC_CMDLINE_PATH, d->pid);
if(access(path, R_OK) != 0) return !ok; /* no such dirent (anymore) */

errno = 0;
// open /proc/[pid]/cmdline
Expand Down Expand Up @@ -328,6 +417,7 @@ void Process::readEnviron()
int fd;

sprintf(path, PROC_ENVIRON_PATH, d->pid);
if(access(path, R_OK) != 0) return; /* no such dirent (anymore) */

errno = 0;
// open /proc/[pid]/environ
Expand Down Expand Up @@ -372,6 +462,7 @@ void Process::readSchedStat()

buf.reserve(bsiz);
sprintf(path, PROC_SCHEDSTAT_PATH, d->pid);
if(access(path, R_OK) != 0) return; /* no such dirent (anymore) */

errno = 0;
// open /proc/[pid]/schedstat
Expand Down Expand Up @@ -405,6 +496,7 @@ bool Process::readStatus()

buf.reserve(bsiz);
sprintf(path, PROC_STATUS_PATH, d->pid);
if(access(path, R_OK) != 0) return !ok; /* no such dirent (anymore) */

errno = 0;
uFile fp(fopen(path, "r"));
Expand Down Expand Up @@ -453,6 +545,7 @@ bool Process::readStatm()
ssize_t nr;

sprintf(path, PROC_STATM_PATH, d->pid);
if(access(path, R_OK) != 0) return !ok; /* no such dirent (anymore) */

errno = 0;
// open /proc/[pid]/statm
Expand Down Expand Up @@ -492,6 +585,7 @@ void Process::readIO()
char path[128], buf[bsiz];

sprintf(path, PROC_IO_PATH, d->pid);
if(access(path, R_OK) != 0) return; /* no such dirent (anymore) */

errno = 0;
// open /proc/[pid]/io
Expand Down Expand Up @@ -524,6 +618,7 @@ void Process::readSockInodes()
struct stat sbuf;

sprintf(path, PROC_FD_PATH, d->pid);
if(access(path, R_OK) != 0) return; /* no such dirent (anymore) */

errno = 0;
// open /proc/[pid]/fd dir
Expand All @@ -548,9 +643,9 @@ void Process::readSockInodes()
} // ::if(stat)
} // ::if(isdigit)
} // ::while(readdir)
if (errno) {
print_errno(errno, QString("read %1 failed").arg(path));
}
// if (errno) {
// print_errno(errno, QString("read %1 failed").arg(path));
// }
}

bool Process::isValid() const
Expand Down
2 changes: 2 additions & 0 deletions deepin-system-monitor-main/process/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ class Process
qulonglong sentBytes() const;

void readProcessInfo();
void readProcessSimpleInfo();
void readProcessVariableInfo();

private:
/**
Expand Down
80 changes: 66 additions & 14 deletions deepin-system-monitor-main/process/process_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "process/process_db.h"
#include "common/common.h"
#include "wm/wm_window_list.h"
#include "settings.h"

#include <QDebug>

Expand All @@ -25,6 +26,11 @@ ProcessSet::ProcessSet()
, m_pidCtoPMapping {}
, m_pidPtoCMapping {}
{
m_prePid.clear();
m_curPid.clear();
m_pidMyApps.clear();
m_simpleSet.clear();
m_settings = Settings::instance();
}

ProcessSet::ProcessSet(const ProcessSet &other)
Expand Down Expand Up @@ -76,7 +82,7 @@ void ProcessSet::scanProcess()
procstage->uptime = iter->procuptime();
m_recentProcStage[iter->pid()] = procstage;
}

m_curPid.clear();
m_set.clear();
m_pidPtoCMapping.clear();
m_pidCtoPMapping.clear();
Expand All @@ -86,15 +92,53 @@ void ProcessSet::scanProcess()
QList<pid_t> appLst;
while (iter.hasNext()) {
Process proc = iter.next();
if (!proc.isValid())
continue;

m_set.insert(proc.pid(), proc);
m_pidPtoCMapping.insert(proc.ppid(), proc.pid());
m_pidCtoPMapping.insert(proc.pid(), proc.ppid());
if(!m_curPid.contains(proc.pid()))
m_curPid.append(proc.pid());

}

if(m_prePid != m_curPid) {
for (const pid_t &pid : m_prePid) {
if(!m_curPid.contains(pid)){
m_prePid.removeAt(pid); //remove disappear process pid
if(m_simpleSet.contains(pid))
m_simpleSet.remove(pid);
if(m_pidMyApps.contains(pid))
m_pidMyApps.removeAt(pid);
}
}

for (const pid_t &pid : m_curPid) {
if(!m_prePid.contains(pid)){ //add new process pid
Process *proc = new Process(pid);
proc->readProcessSimpleInfo();
if(!m_simpleSet.contains(pid))
m_simpleSet.insert(proc->pid(), *proc);

if (proc.appType() == kFilterApps && !wmwindowList->isTrayApp(proc.pid())) {
appLst << proc.pid();
if (proc->appType() == kFilterApps && !wmwindowList->isTrayApp(proc->pid())) {
m_pidMyApps << proc->pid();
}
}
}
m_prePid = m_curPid;
}

const QVariant &vindex = m_settings->getOption(kSettingKeyProcessTabIndex, kFilterApps);
int index = vindex.toInt();

for (const pid_t &pid : m_prePid) {
Process proc = m_simpleSet[pid];
if( ((kFilterApps == index) && (proc.appType()<= kFilterApps)) ||
((kFilterCurrentUser == index) && (proc.appType() <= kFilterCurrentUser)) ||
(kNoFilter == index)) {
proc.readProcessVariableInfo(); //
if (!proc.isValid())
continue;

m_set.insert(proc.pid(), proc);
m_pidPtoCMapping.insert(proc.ppid(), proc.pid());
m_pidCtoPMapping.insert(proc.pid(), proc.ppid());
}
}

Expand All @@ -110,7 +154,7 @@ void ProcessSet::scanProcess()
return b;
};

for (const pid_t &pid : appLst) {
for (const pid_t &pid : m_pidMyApps) {
qreal recvBps = 0;
qreal sendBps = 0;
mergeSubProcNetIO(pid, recvBps, sendBps);
Expand All @@ -120,7 +164,8 @@ void ProcessSet::scanProcess()
mergeSubProcCpu(pid, ptotalCpu);
m_set[pid].setCpu(ptotalCpu);

if (!wmwindowList->isGuiApp(pid)) {
if (!wmwindowList->isGuiApp(pid))
{
// only if no ancestor process is gui app we keep this process
if (m_pidCtoPMapping.contains(pid) &&
anyRootIsGuiProc(m_pidCtoPMapping[pid])) {
Expand Down Expand Up @@ -164,11 +209,9 @@ Process ProcessSet::Iterator::next()
if (m_dirent && isdigit(m_dirent->d_name[0])) {
auto pid = pid_t(atoi(m_dirent->d_name));
Process proc(pid);
proc.readProcessInfo();

advance();

if (proc.isValid())
return proc;
}

Expand All @@ -179,7 +222,10 @@ void ProcessSet::Iterator::advance()
{
while ((m_dirent = readdir(m_dir.get()))) {
if (isdigit(m_dirent->d_name[0]))
break;
if(pid_t(atoi(m_dirent->d_name)) < 10)
continue;
else
break;
}
if (!m_dirent && errno) {
print_errno(errno, "read /proc failed");
Expand All @@ -198,6 +244,8 @@ const Process ProcessSet::getProcessById(pid_t pid) const

QList<pid_t> ProcessSet::getPIDList() const
{
const QVariant &vindex = m_settings->getOption(kSettingKeyProcessTabIndex, kFilterApps);
int index = vindex.toInt();
// 当系统读取到的m_set为空时,通过keys()函数返回会造成段错误 原因是keys函数效率低下,会造成大量的内存拷贝
// 替换方案是
QList<pid_t> pidList {};
Expand All @@ -206,7 +254,11 @@ QList<pid_t> ProcessSet::getPIDList() const
QMap<pid_t, Process>::key_iterator iterBegin = m_set.keyBegin();
for (;iterBegin != m_set.keyEnd(); ++iterBegin) {
pid_t tmpKey = *iterBegin;
pidList.append(tmpKey);
Process proc = m_set[tmpKey];
if( ((kFilterApps == index) && (proc.appType()<= kFilterApps)) ||
((kFilterCurrentUser == index) && (proc.appType() <= kFilterCurrentUser)) ||
(kNoFilter == index))
pidList.append(tmpKey);
if (size != m_set.size())
break;
}
Expand Down
Loading

0 comments on commit 9aaa92d

Please sign in to comment.