]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/util/core_local.h
1 // Copyright (c) 2017-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
13 #include "port/likely.h"
14 #include "port/port.h"
15 #include "util/random.h"
19 // An array of core-local values. Ideally the value type, T, is cache aligned to
20 // prevent false sharing.
22 class CoreLocalArray
{
27 // returns pointer to the element corresponding to the core that the thread
30 // same as above, but also returns the core index, which the client can cache
31 // to reduce how often core ID needs to be retrieved. Only do this if some
32 // inaccuracy is tolerable, as the thread may migrate to a different core.
33 std::pair
<T
*, size_t> AccessElementAndIndex() const;
34 // returns pointer to element for the specified core index. This can be used,
35 // e.g., for aggregation, or if the client caches core index.
36 T
* AccessAtCore(size_t core_idx
) const;
39 std::unique_ptr
<T
[]> data_
;
44 CoreLocalArray
<T
>::CoreLocalArray() {
45 int num_cpus
= static_cast<int>(std::thread::hardware_concurrency());
46 // find a power of two >= num_cpus and >= 8
48 while (1 << size_shift_
< num_cpus
) {
51 data_
.reset(new T
[static_cast<size_t>(1) << size_shift_
]);
55 size_t CoreLocalArray
<T
>::Size() const {
56 return static_cast<size_t>(1) << size_shift_
;
60 T
* CoreLocalArray
<T
>::Access() const {
61 return AccessElementAndIndex().first
;
65 std::pair
<T
*, size_t> CoreLocalArray
<T
>::AccessElementAndIndex() const {
66 int cpuid
= port::PhysicalCoreID();
68 if (UNLIKELY(cpuid
< 0)) {
69 // cpu id unavailable, just pick randomly
70 core_idx
= Random::GetTLSInstance()->Uniform(1 << size_shift_
);
72 core_idx
= static_cast<size_t>(cpuid
& ((1 << size_shift_
) - 1));
74 return {AccessAtCore(core_idx
), core_idx
};
78 T
* CoreLocalArray
<T
>::AccessAtCore(size_t core_idx
) const {
79 assert(core_idx
< static_cast<size_t>(1) << size_shift_
);
80 return &data_
[core_idx
];
83 } // namespace rocksdb