[llvm] [llvm-profgen] Remove temporary perf script files (PR #86668)

Haohai Wen via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 26 19:23:26 PDT 2024


https://github.com/HaohaiWen updated https://github.com/llvm/llvm-project/pull/86668

>From 94b08cee11409739e99e1a791af92441ee03e302 Mon Sep 17 00:00:00 2001
From: Haohai Wen <haohai.wen at intel.com>
Date: Tue, 26 Mar 2024 22:10:34 +0800
Subject: [PATCH 1/3] [llvm-profgen] Remove temporary perf script files

The temporary perf script files converted from perf data will occupy lots
of space for large project. This patch removes them when llvm-profgen
exits normally or receives signals.
---
 llvm/tools/llvm-profgen/PerfReader.cpp   | 19 +++++++++++++++++++
 llvm/tools/llvm-profgen/PerfReader.h     |  7 +++++++
 llvm/tools/llvm-profgen/llvm-profgen.cpp |  2 ++
 3 files changed, 28 insertions(+)

diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index 878147642aa6e7..5ed0f1333cf2eb 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -11,6 +11,7 @@
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Process.h"
+#include "llvm/Support/Signals.h"
 
 #define DEBUG_TYPE "perf-reader"
 
@@ -375,6 +376,9 @@ PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary,
                                           StringRef(ErrorFile)};    // Stderr
   sys::ExecuteAndWait(PerfPath, ScriptMMapArgs, std::nullopt, Redirects);
 
+  PerfScriptReader::markTempFile(PerfTraceFile);
+  PerfScriptReader::markTempFile(ErrorFile);
+
   // Collect the PIDs
   TraceStream TraceIt(PerfTraceFile);
   std::string PIDs;
@@ -992,6 +996,11 @@ bool PerfScriptReader::extractMMap2EventForBinary(ProfiledBinary *Binary,
   return Binary->getName() == BinaryName;
 }
 
+void PerfScriptReader::markTempFile(StringRef FileName) {
+  sys::RemoveFileOnSignal(FileName);
+  TempFiles.push_back(FileName.str());
+}
+
 void PerfScriptReader::parseMMap2Event(TraceStream &TraceIt) {
   MMapEvent MMap;
   if (extractMMap2EventForBinary(Binary, TraceIt.getCurrentLine(), MMap))
@@ -1081,6 +1090,14 @@ PerfContent PerfScriptReader::checkPerfScriptType(StringRef FileName) {
   return PerfContent::UnknownContent;
 }
 
+void PerfScriptReader::removeTempFiles() {
+  for (StringRef FileName : TempFiles) {
+    sys::fs::remove(FileName);
+    sys::DontRemoveFileOnSignal(FileName);
+  }
+  TempFiles.clear();
+}
+
 void HybridPerfReader::generateUnsymbolizedProfile() {
   ProfileIsCS = !IgnoreStackSamples;
   if (ProfileIsCS)
@@ -1220,5 +1237,7 @@ void PerfScriptReader::parsePerfTraces() {
     writeUnsymbolizedProfile(OutputFilename);
 }
 
+SmallVector<std::string, 2> PerfScriptReader::TempFiles;
+
 } // end namespace sampleprof
 } // end namespace llvm
diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h
index e9f619350bf970..6401a4c51c8b10 100644
--- a/llvm/tools/llvm-profgen/PerfReader.h
+++ b/llvm/tools/llvm-profgen/PerfReader.h
@@ -603,6 +603,8 @@ class PerfScriptReader : public PerfReaderBase {
                          std::optional<uint32_t> PIDFilter);
   // Extract perf script type by peaking at the input
   static PerfContent checkPerfScriptType(StringRef FileName);
+  // Remove all temporary files.
+  static void removeTempFiles();
 
 protected:
   // The parsed MMap event
@@ -622,6 +624,8 @@ class PerfScriptReader : public PerfReaderBase {
   // mapping between the binary name and its memory layout.
   static bool extractMMap2EventForBinary(ProfiledBinary *Binary, StringRef Line,
                                          MMapEvent &MMap);
+  // Mark temporary file for future clean up.
+  static void markTempFile(StringRef FileName);
   // Update base address based on mmap events
   void updateBinaryAddress(const MMapEvent &Event);
   // Parse mmap event and update binary address
@@ -662,6 +666,9 @@ class PerfScriptReader : public PerfReaderBase {
   std::set<uint64_t> InvalidReturnAddresses;
   // PID for the process of interest
   std::optional<uint32_t> PIDFilter;
+
+  // Temporary files created by perf script command.
+  static SmallVector<std::string, 2> TempFiles;
 };
 
 /*
diff --git a/llvm/tools/llvm-profgen/llvm-profgen.cpp b/llvm/tools/llvm-profgen/llvm-profgen.cpp
index 3b974e25103ad4..d0ec463f717677 100644
--- a/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -189,5 +189,7 @@ int main(int argc, const char *argv[]) {
     Generator->write();
   }
 
+  PerfScriptReader::removeTempFiles();
+
   return EXIT_SUCCESS;
 }

>From 969af1ed4bf5e69957746c3377557d02ff1a81bd Mon Sep 17 00:00:00 2001
From: Haohai Wen <haohai.wen at intel.com>
Date: Wed, 27 Mar 2024 10:13:27 +0800
Subject: [PATCH 2/3] [Support] Make CleanupInstaller public

This can be used by others to automatically remove temp files.
---
 llvm/include/llvm/Support/ToolOutputFile.h | 26 ++++++++++++----------
 llvm/lib/Support/ToolOutputFile.cpp        |  4 ++--
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/llvm/include/llvm/Support/ToolOutputFile.h b/llvm/include/llvm/Support/ToolOutputFile.h
index e3fb83fdfd2c3f..c16fb03d9b22b9 100644
--- a/llvm/include/llvm/Support/ToolOutputFile.h
+++ b/llvm/include/llvm/Support/ToolOutputFile.h
@@ -18,6 +18,19 @@
 
 namespace llvm {
 
+class CleanupInstaller {
+public:
+  /// The name of the file.
+  std::string Filename;
+
+  /// The flag which indicates whether we should not delete the file.
+  bool Keep;
+
+  StringRef getFilename() { return Filename; }
+  explicit CleanupInstaller(StringRef Filename);
+  ~CleanupInstaller();
+};
+
 /// This class contains a raw_fd_ostream and adds a few extra features commonly
 /// needed for compiler-like tool output files:
 ///   - The file is automatically deleted if the process is killed.
@@ -28,18 +41,7 @@ class ToolOutputFile {
   /// before the raw_fd_ostream is constructed and destructed after the
   /// raw_fd_ostream is destructed. It installs cleanups in its constructor and
   /// uninstalls them in its destructor.
-  class CleanupInstaller {
-  public:
-    /// The name of the file.
-    std::string Filename;
-
-    /// The flag which indicates whether we should not delete the file.
-    bool Keep;
-
-    StringRef getFilename() { return Filename; }
-    explicit CleanupInstaller(StringRef Filename);
-    ~CleanupInstaller();
-  } Installer;
+  CleanupInstaller Installer;
 
   /// Storage for the stream, if we're owning our own stream. This is
   /// intentionally declared after Installer.
diff --git a/llvm/lib/Support/ToolOutputFile.cpp b/llvm/lib/Support/ToolOutputFile.cpp
index 01f7095f3499d9..7a07286882fee0 100644
--- a/llvm/lib/Support/ToolOutputFile.cpp
+++ b/llvm/lib/Support/ToolOutputFile.cpp
@@ -17,14 +17,14 @@ using namespace llvm;
 
 static bool isStdout(StringRef Filename) { return Filename == "-"; }
 
-ToolOutputFile::CleanupInstaller::CleanupInstaller(StringRef Filename)
+CleanupInstaller::CleanupInstaller(StringRef Filename)
     : Filename(std::string(Filename)), Keep(false) {
   // Arrange for the file to be deleted if the process is killed.
   if (!isStdout(Filename))
     sys::RemoveFileOnSignal(Filename);
 }
 
-ToolOutputFile::CleanupInstaller::~CleanupInstaller() {
+CleanupInstaller::~CleanupInstaller() {
   if (isStdout(Filename))
     return;
 

>From e456fa67b223aa60562773bb759d4c03c5e709f5 Mon Sep 17 00:00:00 2001
From: Haohai Wen <haohai.wen at intel.com>
Date: Wed, 27 Mar 2024 10:15:53 +0800
Subject: [PATCH 3/3] Use CleanupInstaller to make code cleaner

---
 llvm/tools/llvm-profgen/PerfReader.cpp   | 21 ++++-----------------
 llvm/tools/llvm-profgen/PerfReader.h     | 15 ++++++++-------
 llvm/tools/llvm-profgen/llvm-profgen.cpp |  2 --
 3 files changed, 12 insertions(+), 26 deletions(-)

diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index 5ed0f1333cf2eb..e9442027aed3fa 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -11,7 +11,7 @@
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Process.h"
-#include "llvm/Support/Signals.h"
+#include "llvm/Support/ToolOutputFile.h"
 
 #define DEBUG_TYPE "perf-reader"
 
@@ -376,8 +376,8 @@ PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary,
                                           StringRef(ErrorFile)};    // Stderr
   sys::ExecuteAndWait(PerfPath, ScriptMMapArgs, std::nullopt, Redirects);
 
-  PerfScriptReader::markTempFile(PerfTraceFile);
-  PerfScriptReader::markTempFile(ErrorFile);
+  PerfScriptReader::TempFileCleanups.emplace_back(PerfTraceFile);
+  PerfScriptReader::TempFileCleanups.emplace_back(ErrorFile);
 
   // Collect the PIDs
   TraceStream TraceIt(PerfTraceFile);
@@ -996,11 +996,6 @@ bool PerfScriptReader::extractMMap2EventForBinary(ProfiledBinary *Binary,
   return Binary->getName() == BinaryName;
 }
 
-void PerfScriptReader::markTempFile(StringRef FileName) {
-  sys::RemoveFileOnSignal(FileName);
-  TempFiles.push_back(FileName.str());
-}
-
 void PerfScriptReader::parseMMap2Event(TraceStream &TraceIt) {
   MMapEvent MMap;
   if (extractMMap2EventForBinary(Binary, TraceIt.getCurrentLine(), MMap))
@@ -1090,14 +1085,6 @@ PerfContent PerfScriptReader::checkPerfScriptType(StringRef FileName) {
   return PerfContent::UnknownContent;
 }
 
-void PerfScriptReader::removeTempFiles() {
-  for (StringRef FileName : TempFiles) {
-    sys::fs::remove(FileName);
-    sys::DontRemoveFileOnSignal(FileName);
-  }
-  TempFiles.clear();
-}
-
 void HybridPerfReader::generateUnsymbolizedProfile() {
   ProfileIsCS = !IgnoreStackSamples;
   if (ProfileIsCS)
@@ -1237,7 +1224,7 @@ void PerfScriptReader::parsePerfTraces() {
     writeUnsymbolizedProfile(OutputFilename);
 }
 
-SmallVector<std::string, 2> PerfScriptReader::TempFiles;
+SmallVector<CleanupInstaller, 2> PerfScriptReader::TempFileCleanups;
 
 } // end namespace sampleprof
 } // end namespace llvm
diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h
index 6401a4c51c8b10..b821cbe13efae6 100644
--- a/llvm/tools/llvm-profgen/PerfReader.h
+++ b/llvm/tools/llvm-profgen/PerfReader.h
@@ -21,6 +21,9 @@ using namespace llvm;
 using namespace sampleprof;
 
 namespace llvm {
+
+class CleanupInstaller;
+
 namespace sampleprof {
 
 // Stream based trace line iterator
@@ -603,8 +606,11 @@ class PerfScriptReader : public PerfReaderBase {
                          std::optional<uint32_t> PIDFilter);
   // Extract perf script type by peaking at the input
   static PerfContent checkPerfScriptType(StringRef FileName);
-  // Remove all temporary files.
-  static void removeTempFiles();
+
+  // Cleanup installers for temporary files created by perf script command.
+  // Those files will be automatically removed when running destructor or
+  // receiving signals.
+  static SmallVector<CleanupInstaller, 2> TempFileCleanups;
 
 protected:
   // The parsed MMap event
@@ -624,8 +630,6 @@ class PerfScriptReader : public PerfReaderBase {
   // mapping between the binary name and its memory layout.
   static bool extractMMap2EventForBinary(ProfiledBinary *Binary, StringRef Line,
                                          MMapEvent &MMap);
-  // Mark temporary file for future clean up.
-  static void markTempFile(StringRef FileName);
   // Update base address based on mmap events
   void updateBinaryAddress(const MMapEvent &Event);
   // Parse mmap event and update binary address
@@ -666,9 +670,6 @@ class PerfScriptReader : public PerfReaderBase {
   std::set<uint64_t> InvalidReturnAddresses;
   // PID for the process of interest
   std::optional<uint32_t> PIDFilter;
-
-  // Temporary files created by perf script command.
-  static SmallVector<std::string, 2> TempFiles;
 };
 
 /*
diff --git a/llvm/tools/llvm-profgen/llvm-profgen.cpp b/llvm/tools/llvm-profgen/llvm-profgen.cpp
index d0ec463f717677..3b974e25103ad4 100644
--- a/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -189,7 +189,5 @@ int main(int argc, const char *argv[]) {
     Generator->write();
   }
 
-  PerfScriptReader::removeTempFiles();
-
   return EXIT_SUCCESS;
 }



More information about the llvm-commits mailing list