llvm.org GIT mirror llvm / 46cf0f0
[ProfileData] Add unit test infrastructure for sample profile reader/writer Summary: Adds support for in-memory round-trip of sample profile data along with basic round trip unit tests. This will also make it easier to include unit tests for future changes to sample profiling. Reviewers: davidxl, dnovillo, silvas Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15211 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255264 91177308-0d34-0410-b5e6-96231b3b80d8 Nathan Slingerland 3 years ago
6 changed file(s) with 188 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
266266 static ErrorOr>
267267 create(StringRef Filename, LLVMContext &C);
268268
269 /// \brief Create a sample profile reader from the supplied memory buffer.
270 static ErrorOr>
271 create(std::unique_ptr &B, LLVMContext &C);
272
269273 protected:
270274 /// \brief Map every function to its associated profile.
271275 ///
2828 /// \brief Sample-based profile writer. Base class.
2929 class SampleProfileWriter {
3030 public:
31 SampleProfileWriter(StringRef Filename, std::error_code &EC,
32 sys::fs::OpenFlags Flags)
33 : OS(Filename, EC, Flags) {}
3431 virtual ~SampleProfileWriter() {}
3532
3633 /// Write sample profiles in \p S for function \p FName.
5451 return sampleprof_error::success;
5552 }
5653
54 raw_ostream &getOutputStream() { return *OutputStream; }
55
5756 /// Profile writer factory.
5857 ///
59 /// Create a new writer based on the value of \p Format.
58 /// Create a new file writer based on the value of \p Format.
6059 static ErrorOr>
6160 create(StringRef Filename, SampleProfileFormat Format);
6261
62 /// Create a new stream writer based on the value of \p Format.
63 /// For testing.
64 static ErrorOr>
65 create(std::unique_ptr &OS, SampleProfileFormat Format);
66
6367 protected:
68 SampleProfileWriter(std::unique_ptr &OS)
69 : OutputStream(std::move(OS)) {}
70
6471 /// \brief Write a file header for the profile file.
6572 virtual std::error_code
6673 writeHeader(const StringMap &ProfileMap) = 0;
6774
6875 /// \brief Output stream where to emit the profile to.
69 raw_fd_ostream OS;
76 std::unique_ptr OutputStream;
7077 };
7178
7279 /// \brief Sample-based profile writer (text format).
7380 class SampleProfileWriterText : public SampleProfileWriter {
7481 public:
75 SampleProfileWriterText(StringRef F, std::error_code &EC)
76 : SampleProfileWriter(F, EC, sys::fs::F_Text), Indent(0) {}
77
7882 std::error_code write(StringRef FName, const FunctionSamples &S) override;
7983
8084 protected:
85 SampleProfileWriterText(std::unique_ptr &OS)
86 : SampleProfileWriter(OS), Indent(0) {}
87
8188 std::error_code
8289 writeHeader(const StringMap &ProfileMap) override {
8390 return sampleprof_error::success;
8895 ///
8996 /// This is used when printing inlined callees.
9097 unsigned Indent;
98
99 friend ErrorOr>
100 SampleProfileWriter::create(std::unique_ptr &OS,
101 SampleProfileFormat Format);
91102 };
92103
93104 /// \brief Sample-based profile writer (binary format).
94105 class SampleProfileWriterBinary : public SampleProfileWriter {
95106 public:
96 SampleProfileWriterBinary(StringRef F, std::error_code &EC)
97 : SampleProfileWriter(F, EC, sys::fs::F_None), NameTable() {}
98
99107 std::error_code write(StringRef F, const FunctionSamples &S) override;
100108
101109 protected:
110 SampleProfileWriterBinary(std::unique_ptr &OS)
111 : SampleProfileWriter(OS), NameTable() {}
112
102113 std::error_code
103114 writeHeader(const StringMap &ProfileMap) override;
104115 std::error_code writeNameIdx(StringRef FName);
109120 void addNames(const FunctionSamples &S);
110121
111122 MapVector NameTable;
123
124 friend ErrorOr>
125 SampleProfileWriter::create(std::unique_ptr &OS,
126 SampleProfileFormat Format);
112127 };
113128
114129 } // End namespace sampleprof
692692 auto BufferOrError = setupMemoryBuffer(Filename);
693693 if (std::error_code EC = BufferOrError.getError())
694694 return EC;
695
696 auto Buffer = std::move(BufferOrError.get());
695 return create(BufferOrError.get(), C);
696 }
697
698 /// \brief Create a sample profile reader based on the format of the input data.
699 ///
700 /// \param B The memory buffer to create the reader from (assumes ownership).
701 ///
702 /// \param Reader The reader to instantiate according to \p Filename's format.
703 ///
704 /// \param C The LLVM context to use to emit diagnostics.
705 ///
706 /// \returns an error code indicating the status of the created reader.
707 ErrorOr>
708 SampleProfileReader::create(std::unique_ptr &B, LLVMContext &C) {
697709 std::unique_ptr Reader;
698 if (SampleProfileReaderBinary::hasFormat(*Buffer))
699 Reader.reset(new SampleProfileReaderBinary(std::move(Buffer), C));
700 else if (SampleProfileReaderGCC::hasFormat(*Buffer))
701 Reader.reset(new SampleProfileReaderGCC(std::move(Buffer), C));
702 else if (SampleProfileReaderText::hasFormat(*Buffer))
703 Reader.reset(new SampleProfileReaderText(std::move(Buffer), C));
710 if (SampleProfileReaderBinary::hasFormat(*B))
711 Reader.reset(new SampleProfileReaderBinary(std::move(B), C));
712 else if (SampleProfileReaderGCC::hasFormat(*B))
713 Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
714 else if (SampleProfileReaderText::hasFormat(*B))
715 Reader.reset(new SampleProfileReaderText(std::move(B), C));
704716 else
705717 return sampleprof_error::unrecognized_format;
706718
3838 /// it needs to be parsed by the SampleProfileReaderText class.
3939 std::error_code SampleProfileWriterText::write(StringRef FName,
4040 const FunctionSamples &S) {
41 auto &OS = *OutputStream;
42
4143 OS << FName << ":" << S.getTotalSamples();
4244 if (Indent == 0)
4345 OS << ":" << S.getHeadSamples();
8385 const auto &ret = NameTable.find(FName);
8486 if (ret == NameTable.end())
8587 return sampleprof_error::truncated_name_table;
86 encodeULEB128(ret->second, OS);
88 encodeULEB128(ret->second, *OutputStream);
8789 return sampleprof_error::success;
8890 }
8991
111113
112114 std::error_code SampleProfileWriterBinary::writeHeader(
113115 const StringMap &ProfileMap) {
116 auto &OS = *OutputStream;
117
114118 // Write file magic identifier.
115119 encodeULEB128(SPMagic(), OS);
116120 encodeULEB128(SPVersion(), OS);
133137
134138 std::error_code SampleProfileWriterBinary::writeBody(StringRef FName,
135139 const FunctionSamples &S) {
140 auto &OS = *OutputStream;
141
136142 if (std::error_code EC = writeNameIdx(FName))
137143 return EC;
138144
175181 /// \returns true if the samples were written successfully, false otherwise.
176182 std::error_code SampleProfileWriterBinary::write(StringRef FName,
177183 const FunctionSamples &S) {
178 encodeULEB128(S.getHeadSamples(), OS);
184 encodeULEB128(S.getHeadSamples(), *OutputStream);
179185 return writeBody(FName, S);
180186 }
181187
182 /// \brief Create a sample profile writer based on the specified format.
188 /// \brief Create a sample profile file writer based on the specified format.
183189 ///
184190 /// \param Filename The file to create.
185191 ///
191197 ErrorOr>
192198 SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
193199 std::error_code EC;
200 std::unique_ptr OS;
201 if (Format == SPF_Binary)
202 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_None));
203 else
204 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_Text));
205 if (EC)
206 return EC;
207
208 return create(OS, Format);
209 }
210
211 /// \brief Create a sample profile stream writer based on the specified format.
212 ///
213 /// \param OS The output stream to store the profile data to.
214 ///
215 /// \param Writer The writer to instantiate according to the specified format.
216 ///
217 /// \param Format Encoding format for the profile file.
218 ///
219 /// \returns an error code indicating the status of the created writer.
220 ErrorOr>
221 SampleProfileWriter::create(std::unique_ptr &OS,
222 SampleProfileFormat Format) {
223 std::error_code EC;
194224 std::unique_ptr Writer;
195225
196226 if (Format == SPF_Binary)
197 Writer.reset(new SampleProfileWriterBinary(Filename, EC));
227 Writer.reset(new SampleProfileWriterBinary(OS));
198228 else if (Format == SPF_Text)
199 Writer.reset(new SampleProfileWriterText(Filename, EC));
229 Writer.reset(new SampleProfileWriterText(OS));
200230 else if (Format == SPF_GCC)
201231 EC = sampleprof_error::unsupported_writing_format;
202232 else
66 add_llvm_unittest(ProfileDataTests
77 CoverageMappingTest.cpp
88 InstrProfTest.cpp
9 SampleProfTest.cpp
910 )
0 //===- unittest/ProfileData/SampleProfTest.cpp -------------------*- C++
1 //-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ProfileData/SampleProfReader.h"
11 #include "llvm/ProfileData/SampleProfWriter.h"
12 #include "gtest/gtest.h"
13
14 #include
15
16 using namespace llvm;
17 using namespace sampleprof;
18
19 static ::testing::AssertionResult NoError(std::error_code EC) {
20 if (!EC)
21 return ::testing::AssertionSuccess();
22 return ::testing::AssertionFailure() << "error " << EC.value() << ": "
23 << EC.message();
24 }
25
26 namespace {
27
28 struct SampleProfTest : ::testing::Test {
29 std::string Data;
30 std::unique_ptr OS;
31 std::unique_ptr Writer;
32 std::unique_ptr Reader;
33
34 SampleProfTest()
35 : Data(), OS(new raw_string_ostream(Data)), Writer(), Reader() {}
36
37 void createWriter(SampleProfileFormat Format) {
38 auto WriterOrErr = SampleProfileWriter::create(OS, Format);
39 ASSERT_TRUE(NoError(WriterOrErr.getError()));
40 Writer = std::move(WriterOrErr.get());
41 }
42
43 void readProfile(std::unique_ptr &Profile) {
44 auto ReaderOrErr = SampleProfileReader::create(Profile, getGlobalContext());
45 ASSERT_TRUE(NoError(ReaderOrErr.getError()));
46 Reader = std::move(ReaderOrErr.get());
47 }
48
49 void testRoundTrip(SampleProfileFormat Format) {
50 createWriter(Format);
51
52 StringRef FooName("_Z3fooi");
53 FunctionSamples FooSamples;
54 FooSamples.addTotalSamples(7711);
55 FooSamples.addHeadSamples(610);
56 FooSamples.addBodySamples(1, 0, 610);
57
58 StringRef BarName("_Z3bari");
59 FunctionSamples BarSamples;
60 BarSamples.addTotalSamples(20301);
61 BarSamples.addHeadSamples(1437);
62 BarSamples.addBodySamples(1, 0, 1437);
63
64 StringMap Profiles;
65 Profiles[FooName] = std::move(FooSamples);
66 Profiles[BarName] = std::move(BarSamples);
67
68 std::error_code EC;
69 EC = Writer->write(Profiles);
70 ASSERT_TRUE(NoError(EC));
71
72 Writer->getOutputStream().flush();
73
74 auto Profile = MemoryBuffer::getMemBufferCopy(Data);
75 readProfile(Profile);
76
77 EC = Reader->read();
78 ASSERT_TRUE(NoError(EC));
79
80 StringMap &ReadProfiles = Reader->getProfiles();
81 ASSERT_EQ(2u, ReadProfiles.size());
82
83 FunctionSamples &ReadFooSamples = ReadProfiles[FooName];
84 ASSERT_EQ(7711u, ReadFooSamples.getTotalSamples());
85 ASSERT_EQ(610u, ReadFooSamples.getHeadSamples());
86
87 FunctionSamples &ReadBarSamples = ReadProfiles[BarName];
88 ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples());
89 ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples());
90 }
91 };
92
93 TEST_F(SampleProfTest, roundtrip_text_profile) {
94 testRoundTrip(SampleProfileFormat::SPF_Text);
95 }
96
97 TEST_F(SampleProfTest, roundtrip_binary_profile) {
98 testRoundTrip(SampleProfileFormat::SPF_Binary);
99 }
100
101 } // end anonymous namespace