summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Frolov <k.frolov@samsung.com>2023-03-21 17:31:25 +0300
committerGleb Balykov/Advanced System SW Lab /SRR/Staff Engineer/Samsung Electronics <g.balykov@samsung.com>2023-04-25 11:18:09 +0300
commitbae00003acd55d6b7f68383816cca8b6981db7b7 (patch)
tree33e2a289072a755589ecd77fd806afc9532f7699
parentf9ad695ef2118b44d15f74591c9bff9da29ddef1 (diff)
downloadheaptrack-bae00003acd55d6b7f68383816cca8b6981db7b7.tar.gz
heaptrack-bae00003acd55d6b7f68383816cca8b6981db7b7.tar.bz2
heaptrack-bae00003acd55d6b7f68383816cca8b6981db7b7.zip
Optimizing heaptrack latency
1. heaptrack_interpret: added ifndef NDEBUG around debugging code 2. heaptrack_interpret: using file buffers to avoid frequent syscalls 3. libprofiler.co: enable libc bufferisation for output file 4. fixed diagnostic messages in heaptrack_interpret
-rw-r--r--src/interpret/heaptrack_interpret.cpp36
-rw-r--r--src/track/outstream/outstream_file.cpp23
-rw-r--r--src/track/outstream/outstream_file.h7
3 files changed, 52 insertions, 14 deletions
diff --git a/src/interpret/heaptrack_interpret.cpp b/src/interpret/heaptrack_interpret.cpp
index 5a9b539..7340e5c 100644
--- a/src/interpret/heaptrack_interpret.cpp
+++ b/src/interpret/heaptrack_interpret.cpp
@@ -24,12 +24,14 @@
#include <algorithm>
#include <cinttypes>
+#include <fstream>
#include <iostream>
#include <sstream>
#include <stdio_ext.h>
#include <tuple>
#include <unordered_map>
#include <vector>
+#include <memory>
#include <cxxabi.h>
@@ -46,6 +48,7 @@
#include "track/outstream/outstream_socket.h"
#include <unistd.h>
+#include <limits.h>
using namespace std;
@@ -455,10 +458,10 @@ outStream* createStream(const char* fileName)
}
if (outputFileName == "-" || outputFileName == "stdout") {
- fprintf(stderr, "will write to stdout");
+ fprintf(stderr, "will write to stdout\n");
return OpenStream<outStreamFILE, FILE*>(stdout);
} else if (outputFileName == "stderr") {
- fprintf(stderr, "will write to stderr");
+ fprintf(stderr, "will write to stderr\n"), fflush(stdout);
return OpenStream<outStreamFILE, FILE*>(stderr);
} else if (outputFileName == "socket") {
uint16_t Port = outStreamSOCKET::DefaultSocketPort;
@@ -515,10 +518,33 @@ outStream* createStream(const char* fileName)
int main(int /*argc*/, char** /*argv*/)
{
// optimize: we only have a single thread
- ios_base::sync_with_stdio(false);
+ // buffers size (around ~32kBytes)
+ const size_t InputBufferSize = 16UL * LINE_MAX;
+ const size_t OutputBufferSize = 16UL * LINE_MAX;
+
+ // set buffer for stdout (for libc)
+ std::unique_ptr<char[]> stdout_buff(new char[OutputBufferSize]);
+ setvbuf(stdout, &stdout_buff[0], _IOFBF, OutputBufferSize);
+
+// ios_base::sync_with_stdio(false);
__fsetlocking(stdout, FSETLOCKING_BYCALLER);
__fsetlocking(stdin, FSETLOCKING_BYCALLER);
+ // avoid synchronization with libc buffers
+ std::ios_base::sync_with_stdio(false);
+
+ // don't flush output before input
+ std::cin.tie(nullptr);
+
+ // use buffered input file `infile': buffer for std::cin can'be
+ // changed, so we need to open /dev/stdin again, but buffer should
+ // be set before opening file or call to `pubsetbuf()' will have no effect.
+ std::ifstream infile;
+ std::unique_ptr<char[]> stdin_buff(new char[InputBufferSize + 1]);
+ infile.rdbuf()->pubsetbuf(&stdin_buff[0], InputBufferSize + 1);
+ infile.open("/dev/stdin");
+ if (!infile.is_open()) exit(EXIT_FAILURE);
+
char *env = getenv("DUMP_HEAPTRACK_INTERPRET_OUTPUT");
outStream* outStream;
if (env) {
@@ -555,7 +581,7 @@ int main(int /*argc*/, char** /*argv*/)
uint64_t leakedManagedAllocations = 0;
uint64_t temporaryAllocations = 0;
- while (reader.getLine(cin)) {
+ while (reader.getLine(infile)) {
if (reader.mode() == 'x') {
reader >> exe;
} else if (reader.mode() == 'm') {
@@ -733,6 +759,7 @@ int main(int /*argc*/, char** /*argv*/)
managedPointersSet.erase(itFromBegin, itFromEnd);
+#ifndef NDEBUG
for (auto ptr : managedPointersSet) {
if(gcManagedPointersSet.find(ptr) != gcManagedPointersSet.end()) {
assert(false);
@@ -743,6 +770,7 @@ int main(int /*argc*/, char** /*argv*/)
assert(false);
}
}
+#endif
} else if (reader.mode() == '+') {
++allocations;
++leakedAllocations;
diff --git a/src/track/outstream/outstream_file.cpp b/src/track/outstream/outstream_file.cpp
index 410cef7..e64ce4a 100644
--- a/src/track/outstream/outstream_file.cpp
+++ b/src/track/outstream/outstream_file.cpp
@@ -3,12 +3,13 @@
#include <cstdio>
#include <cstring>
#include <stdio_ext.h>
-#include <unistd.h>
-#include <fcntl.h>
+#include <unistd.h>
+#include <fcntl.h>
#include "outstream_file.h"
outStreamFILE::outStreamFILE(const char *FileName) :
+ m_buffer(new char[BufferSize]),
Stream_(nullptr),
Owner_(false)
{
@@ -20,13 +21,15 @@ outStreamFILE::outStreamFILE(const char *FileName) :
throw std::runtime_error("Unable to open stream");
}
- int fd = fileno(Stream_);
- if (fd >= 0) {
- if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
- fprintf(stderr, "WARNING! Failed to set FD_CLOEXEC mode for file %s: %s\n", FileName, strerror(errno));
- }
- }
-
+ if (setvbuf(Stream_, &m_buffer[0], _IOFBF, BufferSize) != 0) perror("setvbuf");
+
+ int fd = fileno(Stream_);
+ if (fd >= 0) {
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
+ fprintf(stderr, "WARNING! Failed to set FD_CLOEXEC mode for file %s: %s\n", FileName, strerror(errno));
+ }
+ }
+
Owner_ = true;
// from heaptrack code: we do our own locking, this speeds up the writing significantly
__fsetlocking(Stream_, FSETLOCKING_BYCALLER);
@@ -53,7 +56,7 @@ int outStreamFILE::Putc(int Char) noexcept
errno = EIO;
return EOF;
}
- return fputc(Char, Stream_);
+ return putc(Char, Stream_);
}
int outStreamFILE::Puts(const char *String) noexcept
diff --git a/src/track/outstream/outstream_file.h b/src/track/outstream/outstream_file.h
index 0b0d9f9..f60627e 100644
--- a/src/track/outstream/outstream_file.h
+++ b/src/track/outstream/outstream_file.h
@@ -1,6 +1,9 @@
#ifndef OUTSTREAMFILE_H
#define OUTSTREAMFILE_H
+#include <memory>
+#include <utility>
+#include <limits.h>
#include "outstream.h"
class outStreamFILE final : public outStream
@@ -15,6 +18,7 @@ public:
outStreamFILE &operator = (const outStreamFILE &) = delete;
outStreamFILE(outStreamFILE &&other) :
+ m_buffer(std::move(other.m_buffer)),
Stream_(other.Stream_),
Owner_(other.Owner_)
{
@@ -24,6 +28,7 @@ public:
outStreamFILE &operator = (outStreamFILE &&other) {
Stream_ = other.Stream_;
Owner_ = other.Owner_;
+ m_buffer = std::move(other.m_buffer);
other.Stream_ = nullptr;
other.Owner_ = false;
return *this;
@@ -34,6 +39,8 @@ public:
bool Flush() noexcept override;
private:
+ static const size_t BufferSize = size_t(16) * LINE_MAX; // ~32 kBytes
+ std::unique_ptr<char[]> m_buffer;
FILE *Stream_;
bool Owner_;
};