<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 29 May 2018 at 10:32, Loïc Gelle <span dir="ltr"><<a href="mailto:loic.gelle@polymtl.ca" target="_blank">loic.gelle@polymtl.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I don't understand what you mean by "not sustainable".<br>
</blockquote>
<br></span>
Not something you can keep in your codebase forever.<span class=""><br></span></blockquote><br></div><div class="gmail_quote">I think we're talking past each other on this point. Beyond being "not elegant", I am not aware of Go dropping the support for calling C code.</div><div class="gmail_quote"><br></div><div class="gmail_quote">I am not seeing how this isn't sustainable in the literal sense.<br><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
It really depends on who does it I would guess. It's very probably a couple<br>
of months to get something that is bullet-proof and mergeable.<br>
</blockquote>
<br></span>
Is it on the roadmap for a future version of LTTng?<span class=""><br></span></blockquote><div><br></div><div>It's something we would like to support, but it isn't on the roadmap in the short term, at least. This is not to say it can't be worked on.</div><div><br></div><div>Jérémie<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
Jérémie Galarneau <<a href="mailto:jeremie.galarneau@efficios.com" target="_blank">jeremie.galarneau@efficios.co<wbr>m</a>> a écrit :<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
On 29 May 2018 at 09:47, Loïc Gelle <<a href="mailto:loic.gelle@polymtl.ca" target="_blank">loic.gelle@polymtl.ca</a>> wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I agree that integrating C code into a Go codebase is somewhat inelegant.<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
</blockquote>
<br>
Not only that, but it's not sustainable. It is more a hack than a feature.<br>
<br>
</blockquote>
<br>
<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br><span class="">
However, I'm not sure what you mean by "implementation issues that are<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
specific to the language itself".<br>
<br>
</blockquote>
<br>
I mean that if you put static calls to C tracepoints from a Go program,<br>
you always have a function call (and the ~50ns overhead) triggered each<br>
time you hit the tracepoint, whether the tracepoint is actually enabled or<br>
not. So basically you can't count on the compiler (specific to the<br>
language) to do clever branch prediction for you, which reduces the<br>
interest of instrumenting your code.<br>
<br>
</span></blockquote><span class="">
<br>
In the case of the first solution, note that the agent tracks which events<br>
are enabled or not. In that sense, the check is performed within the Go<br>
code, as is currently done for Python and Java.<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I like the third solution that you propose. I think that the first one is<br>
definitely not ideal and that the second one is too much work and<br>
maintaining. How much time do you estimate is necessary for the development<br>
of the third solution?<br>
<br>
</blockquote>
<br>
<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br><div><div class="h5">
By the way, I am currently working on instrumenting the Go runtime to<br>
capture information on the goroutines. I am using dyntrace (<br>
<a href="https://github.com/charpercyr/dyntrace" rel="noreferrer" target="_blank">https://github.com/charpercyr/<wbr>dyntrace</a>) for that, which kind of works but<br>
is really hacky.<br>
<br>
</div></div></blockquote><div><div class="h5">
<br>
That sounds great. What kind of information are you capturing?<br>
<br>
Thanks,<br>
Jérémie<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Jérémie Galarneau <<a href="mailto:jeremie.galarneau@efficios.com" target="_blank">jeremie.galarneau@efficios.co<wbr>m</a>> a écrit :<br>
<br>
On 28 May 2018 at 10:30, Loïc Gelle <<a href="mailto:loic.gelle@polymtl.ca" target="_blank">loic.gelle@polymtl.ca</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Hi Jeremie,<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Thanks for your answer. I roughly estimated the overhead of calling an<br>
empty C function (passing two integer arguments) from Go to 50ns per<br>
call.<br>
Maybe not a big deal for a lot of use cases, but more problematic if you<br>
want to trace performance-critical parts of Go like its runtime itself.<br>
The<br>
overhead could even be bigger when it involves passing strings or arrays<br>
that have different memory layouts in Golang and C. What was the overhead<br>
that you observed for Python and Java?<br>
<br>
<br>
</blockquote>
50ns per call doesn't sound too bad honestly.<br>
<br>
You have to ask yourself if you could get within 50ns of lttng-ust's<br>
performance with a custom ring buffer implemented in Go.<br>
<br>
To use some very rough numbers, lttng-ust for that payload, takes around<br>
~250ns per event. With Mathieu's work on restartable sequence, that number<br>
will be shaved off quite a bit (by half, if I remember correctly), and I'm<br>
not sure you'll be able to use that kind of mechanism from Go code.<br>
<br>
I don't have numbers on hand for Python and Java. In both cases, we are<br>
hooking into logging frameworks so the overhead of calling into C code<br>
probably pales in comparison to the time spent formatting strings.<br>
That's another problem in using the current "agent" mechanism; it really<br>
only accommodates a very specific tracepoint signature that takes a string<br>
payload.<br>
<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
>From what I understand, it will always be a problem to have agents for<br>
languages different than C, especially if you want to keep relying on<br>
existing C code. Even if the sessiond part is independant from the agent<br>
itself, there are tons of implementation issues that are specific to the<br>
language itself. The problem with Go is that calling C functions is<br>
really<br>
a hack that does not integrate well with the build system that was<br>
designed<br>
for Go.<br>
<br>
<br>
</blockquote>
<br>
The solutions I see:<br>
<br>
1) Replicate the current "agent" scheme and serialize all Go events to<br>
strings<br>
<br>
Not ideal as you lose the events' typing, you have to serialize to strings<br>
on the fast path, and you can hardly filter on event payloads.<br>
<br>
2) Write a native Go ring-buffer that can be consumed by LTTng<br>
<br>
In essence, all the tracing would happen in Go. Events would be serialized<br>
by Go code and the Go "agent" would produce the CTF metadata that<br>
describes<br>
their layout.<br>
<br>
>From an integration standpoint, that's probably the most elegant solution<br>
as you have no hard dependency on native code in your go projects.<br>
However,<br>
it's a _lot_ of work.<br>
<br>
First, you have to re-implement a ring-buffer that needs to perform within<br>
50ns of lttng-ust's ring-buffer to be useful. You also need to port the<br>
event filtering bytecode interpreter to Go.<br>
Then, we need to find a way to consume that ring-buffer's content from a<br>
form of consumer daemon within lttng-tools.<br>
<br>
3) Add an lttng-ust API to allow dynamic event declaration<br>
<br>
This is something we have been considering for a while.<br>
<br>
Basically, we would like to introduce an API that allows applications to<br>
dynamically declare tracepoints.<br>
Then, those events would be serialized from Go, but the ring-buffer logic<br>
would remain in C.<br>
<br>
On each event, we would:<br>
  - Obtain a memory area from lttng-ust (reserve phase, C code called from<br>
Go)<br>
  - Write the event's content to that area (from Go code)<br>
  - Commit the event (C code called from Go)<br>
<br>
With this, you don't have to manually declare tracepoints and integrate<br>
them into a build system to generate providers; the Go application just<br>
needs to link to lttng-ust at runtime.<br>
It's not a perfect solution, but it seems like an interesting compromise.<br>
<br>
<br>
What do you think?<br>
<br>
Jérémie<br>
<br>
<br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Did I provide more context?<br>
<br>
Cheers,<br>
Loïc.<br>
<br>
Jérémie Galarneau <<a href="mailto:jeremie.galarneau@efficios.com" target="_blank">jeremie.galarneau@efficios.co<wbr>m</a>> a écrit :<br>
<br>
On 4 May 2018 at 06:03, Loïc Gelle <<a href="mailto:loic.gelle@polymtl.ca" target="_blank">loic.gelle@polymtl.ca</a>> wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Hi,<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
There has been a previous discussion on the mailing list about porting<br>
LTTng to Golang, about a year ago: <a href="https://lists.lttng.org/" rel="noreferrer" target="_blank">https://lists.lttng.org/</a><br>
pipermail/lttng-dev/2017-June/<wbr>027203.html . This new topic is to<br>
discuss<br>
<br>
more precisely about implementation possibilities.<br>
<br>
Currently, one has to use the the C UST agent from LTTng in order to<br>
instrument Golang programs, and to compile the whole thing using custom<br>
Makefiles and cgo. Here is a recent example that I wrote:<br>
<a href="https://github.com/loicgelle/jaeger-go-lttng-instr" rel="noreferrer" target="_blank">https://github.com/loicgelle/j<wbr>aeger-go-lttng-instr</a><br>
<br>
As you can guess, there are a low of drawbacks in that approach. It is<br>
actually a hack and cannot be integrated into more complex Golang<br>
program<br>
that use a more complex build process (e.g. the Golang runtime itself),<br>
because of the compiler instructions that you have to include at the<br>
top<br>
of<br>
the Golang files. There is also a big concern about the performance of<br>
this<br>
solution, as calling a C function from Go requires to do a full context<br>
switch on the stack, because the calling conventions in C and Golang<br>
are<br>
different.<br>
<br>
<br>
I think a more integrated and performant solution is needed. We can’t<br>
</blockquote>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
really ignore a language such as Golang that is now widely adopted for<br>
cloud applications. LTTng is really the best solution out there in<br>
terms<br>
of<br>
overhead per tracepoint, and could benefit from being made available to<br>
such a large community. My question to the experts on this mailing<br>
list:<br>
how much would it take to write a Golang agent for LTTng?<br>
<br>
<br>
<br>
</blockquote>
Hi Loïc,<br>
<br>
Without having performed any measurements myself, it does seem like<br>
calling<br>
C from Go is very expensive. In that context, I can see that LTTng would<br>
probably lose its performance advantage over any native Go solution.<br>
However, it wouldn't hurt to measure the impact and see if it really is<br>
a<br>
deal breaker.<br>
<br>
We faced the same dilemma when implementing the Java and Python support<br>
in<br>
lttng-ust. In those cases, we ended up calling C code, with the<br>
performance<br>
penalties it implies. The correlation with other applications' and the<br>
kernel's events, along with the rest of LTTng's features, provided<br>
enough<br>
value to make that solution worthwhile.<br>
<br>
There aren't a ton of solutions if we can't call existing C code. We<br>
basically have to reimplement a ring-buffer and the setup/communication<br>
infrastructure to interact with the lttng-sessiond. The communication<br>
with<br>
the session daemon is not a big concern as the protocol is fairly<br>
straightforward.<br>
<br>
The "hairy" part is that lttng-ust and lttng-consumerd use a shared<br>
memory<br>
map to produce and consume the tracing buffers. This means that all<br>
changes<br>
to that memory layout would need to be replicated in the Go tracer,<br>
making<br>
future evolution more difficult. Also, I don't know how easy it would be<br>
to<br>
synchronize C and Go applications interacting in a shared memory map<br>
given<br>
those languages have different memory models. My knowledge of Go doesn't<br>
go<br>
that far.<br>
<br>
A more viable solution could be to introduce a Go-native consumer daemon<br>
implementing its own synchronization with Go applications. This way,<br>
that<br>
implementation could evolve on its own and could also start with a<br>
simpler<br>
ring buffer than lttng-ust's.<br>
<br>
Still, it is not a small undertaking and it basically means maintaining<br>
a<br>
third tracer implementation.<br>
<br>
<br>
What do you think?<br>
<br>
Thanks!<br>
Jérémie<br>
<br>
<br>
Cheers,<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Loïc.<br>
<br>
______________________________<wbr>_________________<br>
lttng-dev mailing list<br>
<a href="mailto:lttng-dev@lists.lttng.org" target="_blank">lttng-dev@lists.lttng.org</a><br>
<a href="https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev" rel="noreferrer" target="_blank">https://lists.lttng.org/cgi-bi<wbr>n/mailman/listinfo/lttng-dev</a><br>
<br>
<br>
<br>
<br>
</blockquote>
--<br>
Jérémie Galarneau<br>
EfficiOS Inc.<br>
<a href="http://www.efficios.com" rel="noreferrer" target="_blank">http://www.efficios.com</a><br>
<br>
<br>
</blockquote>
<br>
<br>
<br>
<br>
</blockquote>
<br>
--<br>
Jérémie Galarneau<br>
EfficiOS Inc.<br>
<a href="http://www.efficios.com" rel="noreferrer" target="_blank">http://www.efficios.com</a><br>
<br>
</blockquote>
<br>
<br>
<br>
<br>
</blockquote>
<br>
<br>
--<br>
Jérémie Galarneau<br>
EfficiOS Inc.<br>
<a href="http://www.efficios.com" rel="noreferrer" target="_blank">http://www.efficios.com</a><br>
</div></div></blockquote>
<br>
<br>
<br>
</blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Jérémie Galarneau<br>EfficiOS Inc.<br><a href="http://www.efficios.com" target="_blank">http://www.efficios.com</a></div>
</div></div>