Skip to content

Commit 15262e0

Browse files
authored
Add valgrind/callgrind instructions and provide makefile.toml targets. (#732)
* Add targets to automate running with callgrind This makes it easy to run the app under valgrind with --callgrind to profile the function calls made. Accessory script utils/symlink-qt-installer-libs-to-pyside6.sh is provided to alter the PySide6 installation with Qt libraries that contain debug information, so the callgrind logs have more useful information in them. * Add valgrind/callgrind instructions to README.md
1 parent 3c11ae7 commit 15262e0

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

Makefile.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ Get-ChildItem .\console_backend -Recurse -Include @("*.egg-info", "*.dist-info")
164164
command = "${PYTHON}"
165165
args = ["-m", "swiftnav_console.main", "${@}"]
166166

167+
[tasks.start-console-callgrind]
168+
command = "valgrind"
169+
args = ["--tool=callgrind", "${PYTHON}", "-m", "swiftnav_console.main", "${@}"]
170+
167171
[tasks.start-console-gdb]
168172
command = "rust-gdb"
169173
args = [
@@ -200,6 +204,16 @@ dependencies = [
200204
]
201205
run_task = "start-console-gdb"
202206

207+
[tasks.callgrind-run]
208+
dependencies = [
209+
"copy-capnp",
210+
"generate-resources",
211+
"remove-egg-dist",
212+
"store-version",
213+
"install-backend",
214+
]
215+
run_task = "start-console-callgrind"
216+
203217
[tasks.prod-run]
204218
dependencies = [
205219
"copy-capnp",

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,45 @@ cargo make check-all
193193
cargo make tests
194194
```
195195

196+
## Callgrind
197+
198+
It may be helpful to profile the application. To do this, you can use valgrind.
199+
One mode of valgrind that is particularly useful is --callgrind.
200+
201+
In order to use this, you need to install valgrind in your favorite OS.
202+
You can initiate this using the cargo make target `callgrind-run`.
203+
204+
Once you run the app with callgrind and quit the application, it will generate a
205+
file named callgrind.out.\<unique id\>.
206+
207+
To analyze the results, use kcachegrind or qcachegrind, which you should be able
208+
to find installable with your distribution's package manager.
209+
Both are the same tool, just have slightly different dependencies. If you are
210+
using KDE, install `kcachegrind`. If you are using Gnome, install `qcachegrind`.
211+
Pass the `callgrind.out` file to the tool like so:
212+
```
213+
qcachegrind callgrind.out.163238
214+
```
215+
216+
To dive into the source code, download the sources for the libraries you wish to
217+
inspect (like Qt or Python), matching the exact version, and set the source
218+
directories in QCacheGrind from the configuration dialog accessible from the
219+
View menu (View-\>Configure...-\>Source Annotation-\>Add).
220+
221+
The Qt libraries contained in the PySide6 python module do not contain debug
222+
symbols, and thus you see limited information from Qt when profiling. To add
223+
debug symbols to this, download and install Qt from qt.io, matching the PySide6
224+
version, and use the included `utils/symlink-qt-installer-libs-to-pyside6.sh`
225+
script.
226+
227+
You can fetch the Qt source code either from the Qt installer, or from git
228+
using the `v6.n.n` tags.
229+
230+
This has only been tested on Linux, but it should also work on macOS and
231+
Windows.
232+
233+
Someone else may be able to expand this showing how to profile the Rust code.
234+
196235
## Technologies
197236

198237
### Rust
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env bash
2+
3+
set -e # Terminate with failure if any command returns nonzero
4+
set -u # Terminate with failure any time an undefined variable is expanded
5+
6+
SCRIPT_DIR="$(cd -P "$(dirname "$BASH_SOURCE")" >/dev/null 2>&1 && pwd)"
7+
8+
pyproject_toml="${SCRIPT_DIR}/../pyproject.toml"
9+
if [[ ! -f "$pyproject_toml" ]]; then
10+
echo >&2 "Couldn't find pyproject.toml."
11+
echo >&2 "Unable to determine PySide6 version. aborting."
12+
exit 0
13+
fi
14+
15+
set +e
16+
awk --version >/dev/null 2>&1
17+
if [[ $? -ne 0 ]]; then
18+
echo >&2 "Couldn't find awk. Aborting."
19+
exit 1
20+
fi
21+
set -e
22+
23+
pysideversion=$(awk '/PySide6/{print(gensub(".*(PySide6 *== *([0-9]\\.[0-9]{1,2}\\.[0-9]{1,3})).*","\\2", "1")) }' "$pyproject_toml")
24+
25+
if [[ ! "$pysideversion" =~ [0-9]\.[0-9]{1,2}\.[0-9]{1,3} ]]; then
26+
echo >&2 "PySide version found is not a version number: $pysideversion"
27+
exit 1
28+
fi
29+
30+
qt_archdir=""
31+
case $OSTYPE in
32+
"linux-gnu"*)
33+
qt_archdir="gcc_64"
34+
;;
35+
"darwin"*)
36+
qt_archdir="macos"
37+
;;
38+
*)
39+
qt_archdir="msvc2019_64"
40+
;;
41+
esac
42+
43+
# Standard Qt install location
44+
QTDIR="${HOME}/Qt/${pysideversion}/${qt_archdir}"
45+
46+
kept_args=()
47+
for arg in "$@"; do
48+
case $arg in
49+
--qtdir=*)
50+
QTDIR="${arg#*=}"
51+
shift
52+
;;
53+
-h|--help)
54+
echo >&2 "$(basename "$BASH_SOURCE") [--qtdir=<Path to Qt base dir>] [-h|--help]"
55+
echo >&2
56+
echo >&2 " --qtdir=<Path to Qt base dir>"
57+
echo >&2 " Use specified Qt dir to link Qt libraries into PySide6 installation."
58+
echo >&2 " -h, --help"
59+
echo >&2 " Show this help."
60+
exit 0
61+
;;
62+
-*|--*)
63+
echo >&2 "Unknown option $arg."
64+
exit 1
65+
;;
66+
*)
67+
kept_args+=($arg)
68+
;;
69+
esac
70+
done
71+
set -- "${kept_args[@]}"
72+
73+
74+
# Check if Qt is installed
75+
if [[ ! -e "${QTDIR}/lib/libQt6Core.so.6" ]]; then
76+
echo >&2 "Could not find ${QTDIR}/lib/libQt6Core.so.6. aborting."
77+
exit 1
78+
fi
79+
80+
# Check if PySide6 is installed
81+
pyside6_qt_lib_dir=$(realpath "${SCRIPT_DIR}/../py39/lib/python3.9/site-packages/PySide6/Qt/lib")
82+
if [[ ! -e "$pyside6_qt_lib_dir" ]]; then
83+
echo >&2 "Could not find $pyside6_qt_lib_dir. aborting."
84+
exit 1
85+
fi
86+
87+
cd "${QTDIR}/lib"
88+
qtdir_libs=$(ls -1 libQt6*.so.6 | sort)
89+
cd "${SCRIPT_DIR}/../py39/lib/python3.9/site-packages/PySide6/Qt/lib"
90+
91+
bkup_dir_suffix=""
92+
while [[ -e "original_libs${bkup_dir_suffix}" ]]; do
93+
if [[ -z "$bkup_dir_suffix" ]]; then
94+
bkup_dir_suffix=1
95+
else
96+
bkup_dir_suffix=$(($bkup_dir_suffix+1))
97+
fi
98+
done
99+
orig_libs_dir="original_libs${bkup_dir_suffix}"
100+
mkdir "$orig_libs_dir"
101+
mv $qtdir_libs "$orig_libs_dir"
102+
103+
for lib in $qtdir_libs ; do
104+
ln -s "${QTDIR}/lib/$lib" $lib
105+
done
106+
107+
echo "Done."
108+
echo "Qt libraries from
109+
$QTDIR
110+
have been linked to
111+
$pyside6_qt_lib_dir"

0 commit comments

Comments
 (0)