Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
KSystemStats
Commits
1cd660c3
Commit
1cd660c3
authored
Nov 10, 2021
by
David Redondo
🏎
Browse files
Intel test
parent
15a03830
Changes
6
Hide whitespace changes
Inline
Side-by-side
plugins/gpu/CMakeLists.txt
View file @
1cd660c3
...
...
@@ -5,7 +5,12 @@ add_library(ksystemstats_plugin_gpu MODULE GpuPlugin.cpp GpuBackend.cpp GpuDevic
target_link_libraries
(
ksystemstats_plugin_gpu Qt::Core KF5::CoreAddons KF5::I18n KSysGuard::SystemStats UDev::UDev
)
if
(
CMAKE_SYSTEM_NAME STREQUAL
"Linux"
)
target_sources
(
ksystemstats_plugin_gpu PRIVATE LinuxAmdGpu.cpp LinuxNvidiaGpu.cpp LinuxBackend.cpp NvidiaSmiProcess.cpp
)
target_sources
(
ksystemstats_plugin_gpu PRIVATE LinuxAmdGpu.cpp
LinuxIntelGpu.cpp
LinuxNvidiaGpu.cpp LinuxBackend.cpp NvidiaSmiProcess.cpp
)
endif
()
install
(
TARGETS ksystemstats_plugin_gpu DESTINATION
${
KSYSTEMSTATS_PLUGIN_INSTALL_DIR
}
)
add_executable
(
ksystemstats_intel_helper IntelHelper.cpp
)
configure_file
(
IntelHelperLocation.h.cmake IntelHelperLocation.h
)
install
(
TARGETS ksystemstats_intel_helper DESTINATION
${
KDE_INSTALL_LIBEXECDIR
}
)
plugins/gpu/IntelHelper.cpp
0 → 100644
View file @
1cd660c3
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include
<array>
#include
<chrono>
#include
<cinttypes>
#include
<cstring>
#include
<cstdlib>
#include
<fstream>
#include
<map>
#include
<iostream>
#include
<drm/i915_drm.h>
#include
<linux/perf_event.h>
#include
<sys/capability.h>
#include
<sys/ioctl.h>
#include
<sys/prctl.h>
#include
<sys/syscall.h>
#include
<unistd.h>
constexpr
auto
eventSourceDir
=
"/sys/bus/event_source/devices/i915"
;
int
i915Type
()
{
const
std
::
string
path
=
eventSourceDir
+
std
::
string
(
"/type"
);
std
::
ifstream
typeFile
(
path
);
if
(
!
typeFile
.
is_open
())
{
std
::
cerr
<<
"Could not open "
<<
path
;
std
::
exit
(
1
);
}
int
type
=
-
1
;
if
(
!
(
typeFile
>>
type
))
{
std
::
cerr
<<
"Error reading type"
;
std
::
exit
(
1
);
}
return
type
;
}
int
perf_open
(
int
type
,
int
config
,
int
group_fd
)
{
perf_event_attr
pe
;
std
::
memset
(
&
pe
,
0
,
sizeof
(
pe
));
pe
.
type
=
type
;
pe
.
size
=
sizeof
(
pe
);
pe
.
config
=
config
;
pe
.
read_format
=
PERF_FORMAT_GROUP
|
PERF_FORMAT_ID
|
PERF_FORMAT_TOTAL_TIME_ENABLED
|
PERF_FORMAT_TOTAL_TIME_ENABLED
;
return
syscall
(
SYS_perf_event_open
,
&
pe
,
-
1
,
0
,
group_fd
,
PERF_FLAG_FD_CLOEXEC
);
}
template
<
int
n
>
struct
read_format
{
std
::
uint64_t
count
;
std
::
uint64_t
time_enabled
;
struct
value
{
std
::
uint64_t
value
;
std
::
uint64_t
id
;
};
std
::
array
<
value
,
n
>
values
;
};
int
main
()
{
const
int
type
=
i915Type
();
int
group_fd
=
-
1
;
// TODO Should we also add sema and wait usages?
constexpr
std
::
array
events
=
{
I915_PMU_INTERRUPTS
,
I915_PMU_ACTUAL_FREQUENCY
,
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_RENDER
,
0
),
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_COPY
,
0
),
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_VIDEO
,
0
),
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_VIDEO_ENHANCE
,
0
)};
std
::
map
<
std
::
uint64_t
,
int
>
idToEvent
;
for
(
const
auto
event
:
events
)
{
const
int
fd
=
perf_open
(
type
,
event
,
group_fd
);
if
(
group_fd
==
-
1
)
{
group_fd
=
fd
;
}
if
(
fd
!=
-
1
)
{
std
::
uint64_t
id
;
ioctl
(
fd
,
PERF_EVENT_IOC_ID
,
&
id
);
idToEvent
.
emplace
(
id
,
event
);
}
}
if
(
group_fd
==
-
1
)
{
std
::
cerr
<<
"Failed opening any event"
<<
std
::
endl
;
return
-
1
;
}
read_format
<
events
.
size
()
>
data
;
while
(
true
)
{
if
(
read
(
group_fd
,
&
data
,
sizeof
(
data
))
<
0
)
{
std
::
cerr
<<
"Error reading events"
<<
std
::
endl
;
return
errno
;
}
std
::
cout
<<
data
.
time_enabled
;
for
(
auto
value
=
data
.
values
.
cbegin
();
value
!=
data
.
values
.
cbegin
()
+
data
.
count
;
++
value
)
{
if
(
!
idToEvent
.
count
(
value
->
id
))
{
std
::
cerr
<<
"Unknown event id"
<<
value
->
id
<<
"
\n
"
;
continue
;
}
switch
(
idToEvent
[
value
->
id
])
{
case
I915_PMU_INTERRUPTS
:
std
::
cout
<<
"|Interrupts"
;
break
;
case
I915_PMU_ACTUAL_FREQUENCY
:
std
::
cout
<<
"|Frequency"
;
break
;
case
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_RENDER
,
0
):
std
::
cout
<<
"|Render"
;
break
;
case
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_COPY
,
0
):
std
::
cout
<<
"|Copy"
;
break
;
case
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_VIDEO
,
0
):
std
::
cout
<<
"|Video"
;
break
;
case
I915_PMU_ENGINE_BUSY
(
I915_ENGINE_CLASS_VIDEO_ENHANCE
,
0
):
std
::
cout
<<
"|Enhance"
;
break
;
}
std
::
cout
<<
"|"
<<
value
->
value
;
}
std
::
cout
<<
std
::
endl
;
sleep
(
1
);
}
}
plugins/gpu/IntelHelperLocation.h.cmake
0 → 100644
View file @
1cd660c3
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: CC0-1.0
*/
#pragma once
constexpr auto helperLocation =
"@KDE_INSTALL_FULL_LIBEXECDIR@/ksystemstats_intel_helper"
;
plugins/gpu/LinuxBackend.cpp
View file @
1cd660c3
...
...
@@ -13,6 +13,7 @@
#include
<libudev.h>
#include
"LinuxAmdGpu.h"
#include
"LinuxIntelGpu.h"
#include
"LinuxNvidiaGpu.h"
// Vendor ID strings, as used in sysfs
...
...
@@ -54,6 +55,8 @@ void LinuxBackend::start()
gpu
=
new
LinuxAmdGpu
{
gpuId
,
gpuName
,
device
};
}
else
if
(
vendor
==
nvidiaVendor
)
{
gpu
=
new
LinuxNvidiaGpu
{
gpuCounter
,
gpuId
,
gpuName
};
}
else
if
(
vendor
==
intelVendor
)
{
gpu
=
new
LinuxIntelGpu
(
gpuId
,
gpuName
);
}
else
{
qDebug
()
<<
"Found unsupported GPU:"
<<
path
;
udev_device_unref
(
device
);
...
...
plugins/gpu/LinuxIntelGpu.cpp
0 → 100644
View file @
1cd660c3
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include
"LinuxIntelGpu.h"
#include
"IntelHelperLocation.h"
#include
<QProcess>
#include
<QStandardPaths>
LinuxIntelGpu
::
LinuxIntelGpu
(
const
QString
&
id
,
const
QString
&
name
)
:
GpuDevice
(
id
,
name
)
{
m_helperProcess
=
new
QProcess
(
this
);
m_helperProcess
->
setProgram
(
helperLocation
);
connect
(
m_helperProcess
,
&
QProcess
::
readyReadStandardOutput
,
this
,
&
LinuxIntelGpu
::
readPerfData
);
connect
(
m_helperProcess
,
&
QProcess
::
readyReadStandardError
,
this
,
[
this
]
{
qCritical
()
<<
m_helperProcess
->
readAllStandardError
();
});
connect
(
this
,
&
GpuDevice
::
subscribedChanged
,
this
,
[
this
](
bool
subscribed
)
{
if
(
subscribed
)
{
m_helperProcess
->
start
();
}
else
{
m_helperProcess
->
terminate
();
}
});
}
void
LinuxIntelGpu
::
readPerfData
()
{
while
(
m_helperProcess
->
canReadLine
())
{
const
QString
line
=
m_helperProcess
->
readLine
();
auto
parts
=
line
.
split
(
"|"
);
if
(
parts
.
size
()
<=
1
||
parts
.
size
()
%
2
==
0
)
{
continue
;
}
quint64
timestamp
=
parts
[
0
].
toULong
();
quint64
timediff
=
timestamp
-
lastTimeStamp
;
double
timeDiffSeconds
=
timediff
/
1e9
;
lastTimeStamp
=
timestamp
;
quint64
usage
=
0
;
for
(
int
i
=
1
;
i
<
parts
.
size
();
i
+=
2
)
{
if
(
parts
[
i
]
==
QLatin1String
(
"Frequency"
))
{
quint64
frequencyCount
=
parts
[
i
+
1
].
toULong
();
m_coreFrequencyProperty
->
setValue
((
frequencyCount
-
lastFrequencyCount
)
/
timeDiffSeconds
);
lastFrequencyCount
=
frequencyCount
;
}
else
if
(
parts
[
i
]
==
QLatin1String
(
"Render"
)
||
parts
[
i
]
==
QLatin1String
(
"Copy"
)
||
parts
[
i
]
==
QLatin1String
(
"Video"
)
||
parts
[
i
]
==
QLatin1String
(
"Enhance"
))
{
// FIXME just adding all the "engines" is wrong (confirmed by testing, can go over 100%)
// Either average or maybe use max, both can be potentially misleading
usage
+=
parts
[
i
+
1
].
toULong
();
}
}
m_usageProperty
->
setValue
((
usage
-
lastUsages
)
*
100
/
timediff
);
lastUsages
=
usage
;
}
}
plugins/gpu/LinuxIntelGpu.h
0 → 100644
View file @
1cd660c3
/*
* SPDX-FileCopyrightText: 2021 David Redondo <kde@david-redondo.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#pragma once
#include
"GpuDevice.h"
class
QProcess
;
class
LinuxIntelGpu
:
public
GpuDevice
{
Q_OBJECT
public:
LinuxIntelGpu
(
const
QString
&
id
,
const
QString
&
name
);
private:
void
readPerfData
();
QProcess
*
m_helperProcess
;
quint64
lastTimeStamp
;
quint64
lastUsages
;
quint64
lastFrequencyCount
;
};
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment