summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--profile-fuse-filesystem.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/profile-fuse-filesystem.py b/profile-fuse-filesystem.py
new file mode 100644
index 000000000..78e6f9826
--- /dev/null
+++ b/profile-fuse-filesystem.py
@@ -0,0 +1,71 @@
+# Profile helper for the SafeHardlinks FUSE filesystem
+#
+# Run inside a project directory!
+
+
+import os
+import signal
+import subprocess
+import sys
+import tempfile
+
+import buildstream
+import buildstream._frontend
+
+
+# This works by monkeypatching the .mount() method on the SafeHardlinks
+# filesystem. The normal implementation in the _fuse.mount module spawns
+# a multiprocessing.Process subprocess to actually run the filesystem
+# and the main process carries on independently. We override that so that
+# it blocks
+def mount_in_process_and_block(self, mountpoint):
+ self._Mount__mountpoint = mountpoint
+
+ self._Mount__operations = self.create_operations()
+
+ print("Mounting a SafeHardlinks filesystem at {} then blocking".format(mountpoint))
+ print("Profile will be written to {}".format(os.path.abspath('fuse.pstats')))
+ print("Try: bwrap --bind {} / --dev /dev --proc /proc --tmpfs /tmp COMMAND".format(mountpoint))
+
+ with tempfile.NamedTemporaryFile('w') as f:
+ f.write("""
+import buildstream, sys\n
+operations = buildstream._fuse.hardlinks.SafeHardlinkOps(sys.argv[2], sys.argv[3])\n
+buildstream._fuse.fuse.FUSE(operations, sys.argv[1], nothreads=True, foreground=True, nonempty=True)\n
+ """)
+ f.flush()
+
+ args = [sys.executable, '-m', 'cProfile', f.name,
+ mountpoint, self.directory, self.tempdir]
+ print(args)
+
+ # Run the FUSE mount as subprocess with profiling enabled.
+ try:
+ p = subprocess.Popen(args)
+ p.wait()
+ except KeyboardInterrupt:
+ print("Terminating on KeyboardInterrupt")
+ p.send_signal(signal.SIGINT)
+ p.wait()
+ print("Returncode: {}".format(p.returncode))
+ raise
+
+
+ # Here's how you'd run the FUSE mount in-process. Your profile gets skewed
+ # by the time spent staging stuff though.
+ #buildstream._fuse.fuse.FUSE(self._Mount__operations,
+ # self._Mount__mountpoint,
+ # nothreads=True, foreground=True, nonempty=True)
+
+
+buildstream._fuse.hardlinks.SafeHardlinks.mount = mount_in_process_and_block
+
+
+if len(sys.argv) != 2:
+ raise RuntimeError("Usage: {} ELEMENT".format(sys.argv[0]))
+
+element = sys.argv[1]
+
+
+cli = buildstream._frontend.main.cli
+cli.main(args=('shell', element), prog_name=cli.name)