Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance for endian read/write functions #3

Merged
merged 5 commits into from
Mar 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 73 additions & 62 deletions wpiutil/examples/writelog/writelog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,89 +7,100 @@

#include <chrono>
#include <iostream>
#include <vector>
#include <array>
#include <string>
#include <numeric>

#include "wpi/DataLog.h"

int main() {
int main(int argc, char** argv) {
using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
using std::chrono::microseconds;

{
auto log = wpi::log::DoubleLog::Open("test.log", wpi::log::CD_CreateAlways);
if (!log) {
wpi::errs() << "could not open log\n";
return EXIT_FAILURE;
}
int kNumRuns = 10;

if (argc == 2)
kNumRuns = std::stoi(argv[1]);

auto testVec = std::vector<std::pair<std::string, void (*)()>>();

testVec.push_back({"50 double append (test.log)", []{
auto log =
wpi::log::DoubleLog::Open("test.log", wpi::log::CD_CreateAlways);

if (!log)
throw std::runtime_error("Could not open log");

for (int i = 0; i < 50; ++i) log->Append(20000 * i, 1.3 * i);
}
}});

{
auto start = high_resolution_clock::now();
{
wpi::log::DoubleLog::Config config;
config.periodicFlush = 1000;
auto log =
wpi::log::DoubleLog::Open("test2.log", wpi::log::CD_CreateAlways);
if (!log) {
wpi::errs() << "could not open log\n";
return EXIT_FAILURE;
}
for (int i = 0; i < 500000; ++i) log->Append(20000 * i, 1.3 * i);
}
auto stop = high_resolution_clock::now();
std::cout << " time: " << duration_cast<microseconds>(stop - start).count()
<< "\n";
}
#if 0
{
std::vector<uint8_t> data;
data.resize(5000);
auto start = high_resolution_clock::now();
{
auto log = wpi::log::DataLog::Open("test2.log", "image", "image", 0,
wpi::log::CD_OpenAlways);
if (!log) {
wpi::errs() << "could not open log\n";
return EXIT_FAILURE;
}
for (int i = 0; i < 1000; ++i) log->Append(20000 * i, data);
}
auto stop = high_resolution_clock::now();
std::cout << " time: " << duration_cast<microseconds>(stop - start).count()
<< "\n";
}
#endif
{
testVec.push_back({"500k double append (test2.log)", []{
wpi::log::DoubleLog::Config config;
config.periodicFlush = 1000;
auto log =
wpi::log::StringLog::Open("test-string.log", wpi::log::CD_CreateAlways);
if (!log) {
wpi::errs() << "could not open log\n";
return EXIT_FAILURE;
}
for (int i = 0; i < 50; ++i) log->Append(20000 * i, "hello");
wpi::log::DoubleLog::Open("test2.log", wpi::log::CD_CreateAlways);

if (!log)
throw std::runtime_error("Could not open log");

for (uint64_t i = 0; i < 500000; ++i) log->Append(20000 * i, 1.3 * i);
}});

/*
testVec.push_back("Int array append (test2.log)", []{
auto data = std::vector<uint8_t>(5000);
auto log = wpi::log::DataLog::Open("test2.log", "image", "image", 0,
wpi::log::CD_OpenAlways);
if (!log)
throw std::runtime_error("Could not open log");

for (int i = 0; i < 1000; ++i) log->Append(20000 * i, data);
}
*/

{
testVec.push_back({"50 string append (test-string.log)", []{
auto log = wpi::log::StringLog::Open("test-string.log",
wpi::log::CD_CreateAlways);
if (!log)
throw std::runtime_error("Could not open log");

for (int i = 0; i < 50; ++i) log->Append(20000 * i, "hello");
}});

testVec.push_back({"Double array append (test-double-array.log)", []{
auto log = wpi::log::DoubleArrayLog::Open("test-double-array.log",
wpi::log::CD_CreateAlways);
if (!log) {
wpi::errs() << "could not open log\n";
return EXIT_FAILURE;
}
if (!log)
throw std::runtime_error("Could not open log");

log->Append(20000, {1, 2, 3});
log->Append(30000, {4, 5});
}
}});

{
testVec.push_back({"String array append (test-string-array.log)", []{
auto log = wpi::log::StringArrayLog::Open("test-string-array.log",
wpi::log::CD_CreateAlways);
if (!log) {
wpi::errs() << "could not open log\n";
return EXIT_FAILURE;
}
if (!log)
throw std::runtime_error("Could not open log");

log->Append(20000, {"Hello", "World"});
log->Append(30000, {"This", "Is", "Fun"});
}});

for (const auto& [name, fn] : testVec) {
auto resVec = std::vector<microseconds::rep>();
std::cout << name << ": ";

for (int i = 0; i < kNumRuns; ++i) {
auto start = high_resolution_clock::now();
fn();
auto stop = high_resolution_clock::now();
resVec.push_back(duration_cast<microseconds>(stop - start).count());
}

std::cout << std::accumulate(resVec.begin(), resVec.end(), 0)/kNumRuns << "us\n";
}

return EXIT_SUCCESS;
Expand Down
5 changes: 5 additions & 0 deletions wpiutil/src/main/native/cpp/DataLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,13 @@ wpi::Expected<DataLog> DataLog::Open(const wpi::Twine& filename,
DataLog log(new DataLogImpl, true);
if (wpi::Error e = log.m_impl->DoOpen(filename, dataType, dataLayout,
recordSize, disp, config))
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8
return std::move(e);
return std::move(log);
#else
return e;
return log;
#endif
}

bool DoubleLog::Append(uint64_t timestamp, double value) {
Expand Down
10 changes: 10 additions & 0 deletions wpiutil/src/main/native/include/wpi/DataLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,11 @@ class DataLogStaticMixin {
if (wpi::Error e =
impl->Check(Derived::kDataType, Derived::kDataLayout,
Derived::kRecordSize, true, checkLayout, true))
#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8
return std::move(e);
#else
return e;
#endif
return Derived(impl, false);
}

Expand Down Expand Up @@ -718,8 +722,14 @@ class DataLogStaticMixin {
if (wpi::Error e = log.GetImpl()->DoOpen(
filename, Derived::kDataType, Derived::kDataLayout,
Derived::kRecordSize, disp, config))

#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8
return std::move(e);
return std::move(log);
#else
return e;
return log;
#endif
}
};

Expand Down
17 changes: 14 additions & 3 deletions wpiutil/src/main/native/include/wpi/Endian.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ inline value_type byte_swap(value_type value, endianness endian) {
/// Swap the bytes of value to match the given endianness.
template<typename value_type, endianness endian>
inline value_type byte_swap(value_type value) {
return byte_swap(value, endian);
if constexpr ((endian != native) && (endian != system_endianness()))
sys::swapByteOrder(value);
return value;
}

/// Read a value of a particular endianness from memory.
Expand All @@ -87,7 +89,13 @@ template<typename value_type,
endianness endian,
std::size_t alignment>
inline value_type read(const void *memory) {
return read<value_type, alignment>(memory, endian);
value_type ret;

memcpy(&ret,
LLVM_ASSUME_ALIGNED(
memory, (detail::PickAlignment<value_type, alignment>::value)),
sizeof(value_type));
return byte_swap<value_type, endian>(ret);
}

/// Read a value of a particular endianness from a buffer, and increment the
Expand Down Expand Up @@ -118,7 +126,10 @@ template<typename value_type,
endianness endian,
std::size_t alignment>
inline void write(void *memory, value_type value) {
write<value_type, alignment>(memory, value, endian);
value = byte_swap<value_type, endian>(value);
memcpy(LLVM_ASSUME_ALIGNED(
memory, (detail::PickAlignment<value_type, alignment>::value)),
&value, sizeof(value_type));
}

template <typename value_type>
Expand Down