Conversation
8d71897 to
2b08e2c
Compare
|
jenkins test make check |
|
jenkins test api |
|
jenkins test make check arm64 |
rzarzynski
left a comment
There was a problem hiding this comment.
The global registry might be worrisome from the performance point of view. I'm not sure we really need it. Please see my comments.
src/common/Thread.h
Outdated
| int cpuid; | ||
| std::string thread_name; | ||
| static std::mutex threadid_name_mutex; | ||
| static std::unordered_map<pthread_t, std::string> threadid_name; |
There was a problem hiding this comment.
Doesn't this look like reinventing the thread local storage?
There was a problem hiding this comment.
It does look like it ... but I'm trying to help Log::dump_recent() find the thread name after a thread ceases to exist.
I'm also worried that a pthread_t may be recycled by the time Log::dump_recent() eventually calls pthread_getname_np().
There was a problem hiding this comment.
I think I understand what's your intention. My point is recording in TLS would happen when the thread is still alive, not at the dump_recent() stage.
2b08e2c to
00386c1
Compare
eebb5a5 to
67d2532
Compare
|
|
jenkins test api |
|
jenkins test make check arm64 |
|
@markhpc so it is on your radar |
|
jenkins test api |
|
jenkins test make check arm64 |
67d2532 to
87ac83c
Compare
|
Practically this map should not grow too huge to cause problems, but still I'm asking this for brevity - are we okay with this? |
rzarzynski
left a comment
There was a problem hiding this comment.
Conceptually seems fine. Hopefully we could use C++'s thread_local for delegating the TLS interaction out.
src/common/Thread.h
Outdated
| * we do not allocate extra memory to store the 32bit global ID | ||
| * we just type cast the 32bit value to a (void*) and save it in the TLS | ||
| */ | ||
| pthread_once(&global_thread_id_key_once, global_thread_id_key_alloc); |
There was a problem hiding this comment.
C++ has the thread_local that takes from you the responsibility for this low level stuff.
src/log/Log.cc
Outdated
| for (const auto& e : t) { | ||
| recent_pthread_ids.emplace(e.m_thread); | ||
| recent_pthread_ids.emplace(std::make_pair(e.m_thread, | ||
| Thread::fetch_thread_name(e.m_global_thread_id))); |
87ac83c to
3e7bdfa
Compare
|
|
jenkins test api |
|
jenkins test windows |
3e7bdfa to
8f7d3f6
Compare
|
src/common/Thread.cc
Outdated
| #endif | ||
|
|
||
| // STATIC | ||
| std::unordered_map<unsigned int, std::array<char, 16>> Thread::threadid_name; |
There was a problem hiding this comment.
| std::unordered_map<unsigned int, std::array<char, 16>> Thread::threadid_name; | |
| std::unordered_map<unsigned int, boost::container::small_vector<char, 16>> Thread::threadid_name; |
src/log/Entry.h
Outdated
| time m_stamp; | ||
| pthread_t m_thread; | ||
| short m_prio, m_subsys; | ||
| unsigned int m_global_thread_id; // for Log::dump_recent() |
There was a problem hiding this comment.
I feel like it would be much simpler to:
- save the thread's name in thread_local storage (once)
- copy the 128 (16 byte) value in this Entry
There was a problem hiding this comment.
But, when the thread is gone during dump_recent(), where does the thread name gets fetched?
There was a problem hiding this comment.
It's in the Entry itself. It can be copied out into the recent_pthread_ids set.
There was a problem hiding this comment.
I want to add that since there is strong interest to get this fix into older releases, I would strongly recommend this simple solution. I suspect the performance and memory cost to be inconsequential. It can be explored afterwards whether optimizations are worthwhile.
There was a problem hiding this comment.
I had indeed started this PR with copying the thread name into the Entry object ... but was discouraged by Radek to do so due to memory and time consumption in the hot path
There was a problem hiding this comment.
Nope, it wasn't just copying of 16 bytes; it was a call to the lock-protected Thread::fetch_thread_name() (#60058 (comment)) which spurs the concern.
IIUC Patrick is arguing for the simpler approach where the thread name is copied from TLS by the Entry constructor:
Maybe instead of this complex, lock-protected container every
Threadcould cache its name in athread_localvariable from which theEntryconstructor would simply copy?
There was a problem hiding this comment.
Okay, then we wouldn't require any thread local storage at all.
We could simply call ceph_pthread_getname(pthread_self(), ...) in the Entry constructor and save it for future reference.
Does this sound reasonable ?
There was a problem hiding this comment.
This is what I understand:
- Save the thread name (once) in TLS during thread creation (one call to pthread_getname_np(...))
- In the ctor for Entry, fetch the thread name from TLS (no locking required)
- copy the thread name in the Entry object
So, repeated calls to pthread_getname_np(...) is avoided and the overhead is the 16byte copy.
There was a problem hiding this comment.
Discussed this with @mchangir a bit and it's boiling down to deciding if we want to store the thread name in TLS vs calling pthread_getname_np() when creating Entry object. As @rzarzynski mentioned, the pthread call might have a more optimized implementation. So, I'm really on the fence hence to choose between the two.
src/common/Thread.cc
Outdated
| #endif | ||
|
|
||
| // Thread Local Storage | ||
| thread_local unsigned int global_thread_id = 0; |
There was a problem hiding this comment.
C++ allows for thread_local static class member while the ID (or cached thread name) conceptually belongs to Thread.
The global in the name is bit misleading IMHO.
|
jenkins test api |
|
jenkins test windows |
|
jenkins test api |
|
jenkins test windows |
|
jenkins test make check arm64 |
30d4875 to
f385c43
Compare
|
f385c43 to
1837811
Compare
|
jenkins test api |
|
jenkins test make check arm64 |
* pthread name is saved in a thread_local storage * the thread_local name is copied into Entry object's ctor * Log::dump_recent() reads the thread name from the Entry object's data member when dumping logs Fixes: https://tracker.ceph.com/issues/50743 Signed-off-by: Milind Changire <mchangir@redhat.com>
1837811 to
0be8d01
Compare
|
|
jenkins test api |
|
jenkins test make check |
| int detach(); | ||
| int set_affinity(int cpuid); | ||
| static const std::string get_thread_name() { | ||
| return Thread::thread_name; |
There was a problem hiding this comment.
There are many threads in Ceph (and the MDS) which do not use this class Thread. So the "name" will wrongly be empty every time this is called.
There was a problem hiding this comment.
It might be a good idea to make those threads use Thread class then.
There was a problem hiding this comment.
I think the idea behind helpers like make_named_thread() was the opposite -- slowly move off of Thread and just use std::thread.
pthread name is saved against the pthread ID in a class-wide static unordered_map as part of the Thread class
save/fetch methods are implemented to manage the thread names
thread names are never removed from the map
Fixes: https://tracker.ceph.com/issues/50743
Signed-off-by: Milind Changire mchangir@redhat.com
Contribution Guidelines
To sign and title your commits, please refer to Submitting Patches to Ceph.
If you are submitting a fix for a stable branch (e.g. "quincy"), please refer to Submitting Patches to Ceph - Backports for the proper workflow.
When filling out the below checklist, you may click boxes directly in the GitHub web UI. When entering or editing the entire PR message in the GitHub web UI editor, you may also select a checklist item by adding an
xbetween the brackets:[x]. Spaces and capitalization matter when checking off items this way.Checklist
Show available Jenkins commands
jenkins retest this pleasejenkins test classic perfjenkins test crimson perfjenkins test signedjenkins test make checkjenkins test make check arm64jenkins test submodulesjenkins test dashboardjenkins test dashboard cephadmjenkins test apijenkins test docsjenkins render docsjenkins test ceph-volume alljenkins test ceph-volume toxjenkins test windowsjenkins test rook e2e