This is an archive of the discontinued LLVM Phabricator instance.

[XRay] [compiler-rt] Write buffer length to FDR log before writing buffer.
ClosedPublic

Authored by kpw on Mar 27 2017, 1:20 AM.

Details

Summary

Currently the FDR log writer, upon flushing, dumps a sequence of buffers from
its freelist to disk. A reader can read the first buffer up to an EOB record,
but then it is unclear how far ahead to scan to find the next threads traces.

There are a few ways to handle this problem.

  1. The reader has externalized knowledge of the buffer size.
  2. The size of buffers is in the file header or otherwise encoded in the log.
  3. Only write out the portion of the buffer with records. When released, the buffers are marked with a size.
  4. The reader looks for memory that matches a pattern and synchronizes on it.

2 and 3 seem the most flexible and 2 does not rule 3 out.

This is an implementation of 2.

In addition, the function handler for fdr more aggressively checks for
finalization and makes an attempt to release its buffer.

Diff Detail

Repository
rL LLVM

Event Timeline

kpw created this revision.Mar 27 2017, 1:20 AM
dberris requested changes to this revision.Mar 27 2017, 7:17 PM

I think I prefer putting FDR-specific information in the padding data available for the header record. We can use more bytes in the 32-byte XRayFileHeader to encode the FDR log buffer size, and if you want potentially the number of buffers as well.

This revision now requires changes to proceed.Mar 27 2017, 7:17 PM
kpw added a comment.Mar 27 2017, 8:38 PM

I thought about using the header as well. If we go that route, we can't decide to optimize to only flush up through the EOB without confusing readers that aren't equipped with a per buffer frame. It seemed a little odd to have FDR specific fields in the shared header struct as well although we could always fork it into two.

That's fine if we're designing for the common case where recording is turned on for long enough to use many buffers before flushing.

We've got 30 bits left in the bitfield (although Trace.cpp ignores the timespec struct field when reading). xray_buffer_queue.h defines the buffer size as a size_t. What do you think is a reasonable maximum to limit it? I'll change or least comment the header there to keep things honest.

In D31384#711851, @kpw wrote:

I thought about using the header as well. If we go that route, we can't decide to optimize to only flush up through the EOB without confusing readers that aren't equipped with a per buffer frame. It seemed a little odd to have FDR specific fields in the shared header struct as well although we could always fork it into two.

We can make it explicit, by reserving the bytes right away in the header as an array of char's. This way we can pack whatever data we want in the remaining bytes in the header. Since we already record the type of the log in the header, we can get away with having a bit more information that way.

That's fine if we're designing for the common case where recording is turned on for long enough to use many buffers before flushing.

We've got 30 bits left in the bitfield (although Trace.cpp ignores the timespec struct field when reading). xray_buffer_queue.h defines the buffer size as a size_t. What do you think is a reasonable maximum to limit it? I'll change or least comment the header there to keep things honest.

I see that this is in the head of a specific buffer. I'm not opposed to that change. I think we can put the size of the buffer as size_t in the file header, and when we're writing the records in the buffer do the computation (like you're doing) to figure out the number of bytes that's valid in the specific buffer. While the current implementation just dumps the data for the full sized buffer, I agree with you there should be nothing stopping us from writing down just the bytes that matter for a specific buffer.

I don't think we should be limiting the possible size of the buffers artificially -- it's one of those things that really ought to be tunable through flags (which it currently isn't, but is something we can do later).

kpw updated this revision to Diff 93324.Mar 28 2017, 5:24 PM
kpw edited edge metadata.

writing the file sizes to the file header rather than a separate piece of data.

dberris accepted this revision.Mar 28 2017, 5:32 PM

LGTM

Please rebase to the tip of trunk / master, and I'll land once that's done. :)

lib/xray/xray_fdr_logging_impl.h
312 ↗(On Diff #93324)

You probably need to rebase, we're no longer using std::atomic<...> for these data structures.

This revision is now accepted and ready to land.Mar 28 2017, 5:32 PM
kpw updated this revision to Diff 93332.Mar 28 2017, 7:07 PM

Rebasing onto master.

kpw added a comment.EditedMar 28 2017, 7:09 PM

Something in the rebase broke and I'm getting segfaults when instrumenting my test program whether I'm on my branch or master.

It's unrelated to this change, but we'll have to track it down. It happens when calling finalize().

Somewhere between d218b6eb8 and trunk ( a lot of commits ).

This revision was automatically updated to reflect the committed changes.