[llvm] r255264 - [ProfileData] Add unit test infrastructure for sample profile reader/writer
Nathan Slingerland via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 10 09:21:43 PST 2015
Author: slingn
Date: Thu Dec 10 11:21:42 2015
New Revision: 255264
URL: http://llvm.org/viewvc/llvm-project?rev=255264&view=rev
Log:
[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
Added:
llvm/trunk/unittests/ProfileData/SampleProfTest.cpp
Modified:
llvm/trunk/include/llvm/ProfileData/SampleProfReader.h
llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h
llvm/trunk/lib/ProfileData/SampleProfReader.cpp
llvm/trunk/lib/ProfileData/SampleProfWriter.cpp
llvm/trunk/unittests/ProfileData/CMakeLists.txt
Modified: llvm/trunk/include/llvm/ProfileData/SampleProfReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfReader.h?rev=255264&r1=255263&r2=255264&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/SampleProfReader.h (original)
+++ llvm/trunk/include/llvm/ProfileData/SampleProfReader.h Thu Dec 10 11:21:42 2015
@@ -267,6 +267,10 @@ public:
static ErrorOr<std::unique_ptr<SampleProfileReader>>
create(StringRef Filename, LLVMContext &C);
+ /// \brief Create a sample profile reader from the supplied memory buffer.
+ static ErrorOr<std::unique_ptr<SampleProfileReader>>
+ create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C);
+
protected:
/// \brief Map every function to its associated profile.
///
Modified: llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h?rev=255264&r1=255263&r2=255264&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h (original)
+++ llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h Thu Dec 10 11:21:42 2015
@@ -29,9 +29,6 @@ enum SampleProfileFormat { SPF_None = 0,
/// \brief Sample-based profile writer. Base class.
class SampleProfileWriter {
public:
- SampleProfileWriter(StringRef Filename, std::error_code &EC,
- sys::fs::OpenFlags Flags)
- : OS(Filename, EC, Flags) {}
virtual ~SampleProfileWriter() {}
/// Write sample profiles in \p S for function \p FName.
@@ -55,30 +52,40 @@ public:
return sampleprof_error::success;
}
+ raw_ostream &getOutputStream() { return *OutputStream; }
+
/// Profile writer factory.
///
- /// Create a new writer based on the value of \p Format.
+ /// Create a new file writer based on the value of \p Format.
static ErrorOr<std::unique_ptr<SampleProfileWriter>>
create(StringRef Filename, SampleProfileFormat Format);
+ /// Create a new stream writer based on the value of \p Format.
+ /// For testing.
+ static ErrorOr<std::unique_ptr<SampleProfileWriter>>
+ create(std::unique_ptr<raw_ostream> &OS, SampleProfileFormat Format);
+
protected:
+ SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
+ : OutputStream(std::move(OS)) {}
+
/// \brief Write a file header for the profile file.
virtual std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) = 0;
/// \brief Output stream where to emit the profile to.
- raw_fd_ostream OS;
+ std::unique_ptr<raw_ostream> OutputStream;
};
/// \brief Sample-based profile writer (text format).
class SampleProfileWriterText : public SampleProfileWriter {
public:
- SampleProfileWriterText(StringRef F, std::error_code &EC)
- : SampleProfileWriter(F, EC, sys::fs::F_Text), Indent(0) {}
-
std::error_code write(StringRef FName, const FunctionSamples &S) override;
protected:
+ SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
+ : SampleProfileWriter(OS), Indent(0) {}
+
std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override {
return sampleprof_error::success;
@@ -89,17 +96,21 @@ private:
///
/// This is used when printing inlined callees.
unsigned Indent;
+
+ friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
+ SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
+ SampleProfileFormat Format);
};
/// \brief Sample-based profile writer (binary format).
class SampleProfileWriterBinary : public SampleProfileWriter {
public:
- SampleProfileWriterBinary(StringRef F, std::error_code &EC)
- : SampleProfileWriter(F, EC, sys::fs::F_None), NameTable() {}
-
std::error_code write(StringRef F, const FunctionSamples &S) override;
protected:
+ SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
+ : SampleProfileWriter(OS), NameTable() {}
+
std::error_code
writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
std::error_code writeNameIdx(StringRef FName);
@@ -110,6 +121,10 @@ private:
void addNames(const FunctionSamples &S);
MapVector<StringRef, uint32_t> NameTable;
+
+ friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
+ SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
+ SampleProfileFormat Format);
};
} // End namespace sampleprof
Modified: llvm/trunk/lib/ProfileData/SampleProfReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfReader.cpp?rev=255264&r1=255263&r2=255264&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProfReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProfReader.cpp Thu Dec 10 11:21:42 2015
@@ -693,15 +693,27 @@ SampleProfileReader::create(StringRef Fi
auto BufferOrError = setupMemoryBuffer(Filename);
if (std::error_code EC = BufferOrError.getError())
return EC;
+ return create(BufferOrError.get(), C);
+}
- auto Buffer = std::move(BufferOrError.get());
+/// \brief Create a sample profile reader based on the format of the input data.
+///
+/// \param B The memory buffer to create the reader from (assumes ownership).
+///
+/// \param Reader The reader to instantiate according to \p Filename's format.
+///
+/// \param C The LLVM context to use to emit diagnostics.
+///
+/// \returns an error code indicating the status of the created reader.
+ErrorOr<std::unique_ptr<SampleProfileReader>>
+SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) {
std::unique_ptr<SampleProfileReader> Reader;
- if (SampleProfileReaderBinary::hasFormat(*Buffer))
- Reader.reset(new SampleProfileReaderBinary(std::move(Buffer), C));
- else if (SampleProfileReaderGCC::hasFormat(*Buffer))
- Reader.reset(new SampleProfileReaderGCC(std::move(Buffer), C));
- else if (SampleProfileReaderText::hasFormat(*Buffer))
- Reader.reset(new SampleProfileReaderText(std::move(Buffer), C));
+ if (SampleProfileReaderBinary::hasFormat(*B))
+ Reader.reset(new SampleProfileReaderBinary(std::move(B), C));
+ else if (SampleProfileReaderGCC::hasFormat(*B))
+ Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
+ else if (SampleProfileReaderText::hasFormat(*B))
+ Reader.reset(new SampleProfileReaderText(std::move(B), C));
else
return sampleprof_error::unrecognized_format;
Modified: llvm/trunk/lib/ProfileData/SampleProfWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfWriter.cpp?rev=255264&r1=255263&r2=255264&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProfWriter.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProfWriter.cpp Thu Dec 10 11:21:42 2015
@@ -39,6 +39,8 @@ using namespace llvm;
/// it needs to be parsed by the SampleProfileReaderText class.
std::error_code SampleProfileWriterText::write(StringRef FName,
const FunctionSamples &S) {
+ auto &OS = *OutputStream;
+
OS << FName << ":" << S.getTotalSamples();
if (Indent == 0)
OS << ":" << S.getHeadSamples();
@@ -84,7 +86,7 @@ std::error_code SampleProfileWriterBinar
const auto &ret = NameTable.find(FName);
if (ret == NameTable.end())
return sampleprof_error::truncated_name_table;
- encodeULEB128(ret->second, OS);
+ encodeULEB128(ret->second, *OutputStream);
return sampleprof_error::success;
}
@@ -112,6 +114,8 @@ void SampleProfileWriterBinary::addNames
std::error_code SampleProfileWriterBinary::writeHeader(
const StringMap<FunctionSamples> &ProfileMap) {
+ auto &OS = *OutputStream;
+
// Write file magic identifier.
encodeULEB128(SPMagic(), OS);
encodeULEB128(SPVersion(), OS);
@@ -134,6 +138,8 @@ std::error_code SampleProfileWriterBinar
std::error_code SampleProfileWriterBinary::writeBody(StringRef FName,
const FunctionSamples &S) {
+ auto &OS = *OutputStream;
+
if (std::error_code EC = writeNameIdx(FName))
return EC;
@@ -176,11 +182,11 @@ std::error_code SampleProfileWriterBinar
/// \returns true if the samples were written successfully, false otherwise.
std::error_code SampleProfileWriterBinary::write(StringRef FName,
const FunctionSamples &S) {
- encodeULEB128(S.getHeadSamples(), OS);
+ encodeULEB128(S.getHeadSamples(), *OutputStream);
return writeBody(FName, S);
}
-/// \brief Create a sample profile writer based on the specified format.
+/// \brief Create a sample profile file writer based on the specified format.
///
/// \param Filename The file to create.
///
@@ -192,12 +198,36 @@ std::error_code SampleProfileWriterBinar
ErrorOr<std::unique_ptr<SampleProfileWriter>>
SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
std::error_code EC;
+ std::unique_ptr<raw_ostream> OS;
+ if (Format == SPF_Binary)
+ OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_None));
+ else
+ OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_Text));
+ if (EC)
+ return EC;
+
+ return create(OS, Format);
+}
+
+/// \brief Create a sample profile stream writer based on the specified format.
+///
+/// \param OS The output stream to store the profile data to.
+///
+/// \param Writer The writer to instantiate according to the specified format.
+///
+/// \param Format Encoding format for the profile file.
+///
+/// \returns an error code indicating the status of the created writer.
+ErrorOr<std::unique_ptr<SampleProfileWriter>>
+SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
+ SampleProfileFormat Format) {
+ std::error_code EC;
std::unique_ptr<SampleProfileWriter> Writer;
if (Format == SPF_Binary)
- Writer.reset(new SampleProfileWriterBinary(Filename, EC));
+ Writer.reset(new SampleProfileWriterBinary(OS));
else if (Format == SPF_Text)
- Writer.reset(new SampleProfileWriterText(Filename, EC));
+ Writer.reset(new SampleProfileWriterText(OS));
else if (Format == SPF_GCC)
EC = sampleprof_error::unsupported_writing_format;
else
Modified: llvm/trunk/unittests/ProfileData/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/CMakeLists.txt?rev=255264&r1=255263&r2=255264&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/CMakeLists.txt (original)
+++ llvm/trunk/unittests/ProfileData/CMakeLists.txt Thu Dec 10 11:21:42 2015
@@ -7,4 +7,5 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(ProfileDataTests
CoverageMappingTest.cpp
InstrProfTest.cpp
+ SampleProfTest.cpp
)
Added: llvm/trunk/unittests/ProfileData/SampleProfTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/SampleProfTest.cpp?rev=255264&view=auto
==============================================================================
--- llvm/trunk/unittests/ProfileData/SampleProfTest.cpp (added)
+++ llvm/trunk/unittests/ProfileData/SampleProfTest.cpp Thu Dec 10 11:21:42 2015
@@ -0,0 +1,102 @@
+//===- unittest/ProfileData/SampleProfTest.cpp -------------------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/SampleProfReader.h"
+#include "llvm/ProfileData/SampleProfWriter.h"
+#include "gtest/gtest.h"
+
+#include <cstdarg>
+
+using namespace llvm;
+using namespace sampleprof;
+
+static ::testing::AssertionResult NoError(std::error_code EC) {
+ if (!EC)
+ return ::testing::AssertionSuccess();
+ return ::testing::AssertionFailure() << "error " << EC.value() << ": "
+ << EC.message();
+}
+
+namespace {
+
+struct SampleProfTest : ::testing::Test {
+ std::string Data;
+ std::unique_ptr<raw_ostream> OS;
+ std::unique_ptr<SampleProfileWriter> Writer;
+ std::unique_ptr<SampleProfileReader> Reader;
+
+ SampleProfTest()
+ : Data(), OS(new raw_string_ostream(Data)), Writer(), Reader() {}
+
+ void createWriter(SampleProfileFormat Format) {
+ auto WriterOrErr = SampleProfileWriter::create(OS, Format);
+ ASSERT_TRUE(NoError(WriterOrErr.getError()));
+ Writer = std::move(WriterOrErr.get());
+ }
+
+ void readProfile(std::unique_ptr<MemoryBuffer> &Profile) {
+ auto ReaderOrErr = SampleProfileReader::create(Profile, getGlobalContext());
+ ASSERT_TRUE(NoError(ReaderOrErr.getError()));
+ Reader = std::move(ReaderOrErr.get());
+ }
+
+ void testRoundTrip(SampleProfileFormat Format) {
+ createWriter(Format);
+
+ StringRef FooName("_Z3fooi");
+ FunctionSamples FooSamples;
+ FooSamples.addTotalSamples(7711);
+ FooSamples.addHeadSamples(610);
+ FooSamples.addBodySamples(1, 0, 610);
+
+ StringRef BarName("_Z3bari");
+ FunctionSamples BarSamples;
+ BarSamples.addTotalSamples(20301);
+ BarSamples.addHeadSamples(1437);
+ BarSamples.addBodySamples(1, 0, 1437);
+
+ StringMap<FunctionSamples> Profiles;
+ Profiles[FooName] = std::move(FooSamples);
+ Profiles[BarName] = std::move(BarSamples);
+
+ std::error_code EC;
+ EC = Writer->write(Profiles);
+ ASSERT_TRUE(NoError(EC));
+
+ Writer->getOutputStream().flush();
+
+ auto Profile = MemoryBuffer::getMemBufferCopy(Data);
+ readProfile(Profile);
+
+ EC = Reader->read();
+ ASSERT_TRUE(NoError(EC));
+
+ StringMap<FunctionSamples> &ReadProfiles = Reader->getProfiles();
+ ASSERT_EQ(2u, ReadProfiles.size());
+
+ FunctionSamples &ReadFooSamples = ReadProfiles[FooName];
+ ASSERT_EQ(7711u, ReadFooSamples.getTotalSamples());
+ ASSERT_EQ(610u, ReadFooSamples.getHeadSamples());
+
+ FunctionSamples &ReadBarSamples = ReadProfiles[BarName];
+ ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples());
+ ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples());
+ }
+};
+
+TEST_F(SampleProfTest, roundtrip_text_profile) {
+ testRoundTrip(SampleProfileFormat::SPF_Text);
+}
+
+TEST_F(SampleProfTest, roundtrip_binary_profile) {
+ testRoundTrip(SampleProfileFormat::SPF_Binary);
+}
+
+} // end anonymous namespace
More information about the llvm-commits
mailing list