Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prefetch first matched value #2

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ auto_sources(hfiles "*.h" "RECURSE" "${FOLLY_DIR}")
REMOVE_MATCHES_FROM_LISTS(files hfiles
MATCHES
"^${FOLLY_DIR}/build/"
"^${FOLLY_DIR}/experimental/exception_tracer/"
"^${FOLLY_DIR}/futures/exercises/"
"^${FOLLY_DIR}/logging/example/"
"^${FOLLY_DIR}/(.*/)?test/"
Expand Down
5 changes: 5 additions & 0 deletions folly/container/F14Map.h
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,11 @@ class F14BasicMap {
return table_.prehash(key);
}

template <typename K>
void prefetchFirstMatchedValue(K const& key) const {
return table_.prefetchFirstMatchedValue(key);
}

FOLLY_ALWAYS_INLINE iterator find(key_type const& key) {
return table_.makeIter(table_.find(key));
}
Expand Down
30 changes: 18 additions & 12 deletions folly/container/detail/F14Policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,13 @@ class ValueContainerIterator : public ValueContainerIteratorBase<ValuePtr> {
return cur;
}

bool operator==(ValueContainerIterator<ValueConstPtr> const& rhs) const {
return underlying_ == rhs.underlying_;
friend bool operator==(ValueContainerIterator const& lhs,
ValueContainerIterator const& rhs) {
return lhs.underlying_ == rhs.underlying_;
}
bool operator!=(ValueContainerIterator<ValueConstPtr> const& rhs) const {
return !(*this == rhs);
friend bool operator!=(ValueContainerIterator const& lhs,
ValueContainerIterator const& rhs) {
return !(lhs == rhs);
}

private:
Expand Down Expand Up @@ -698,11 +700,13 @@ class NodeContainerIterator : public BaseIter<ValuePtr, NonConstPtr<ValuePtr>> {
return cur;
}

bool operator==(NodeContainerIterator<ValueConstPtr> const& rhs) const {
return underlying_ == rhs.underlying_;
friend bool operator==(NodeContainerIterator const& lhs,
NodeContainerIterator const& rhs) {
return lhs.underlying_ == rhs.underlying_;
}
bool operator!=(NodeContainerIterator<ValueConstPtr> const& rhs) const {
return !(*this == rhs);
friend bool operator!=(NodeContainerIterator const& lhs,
NodeContainerIterator const& rhs) {
return !(lhs == rhs);
}

private:
Expand Down Expand Up @@ -936,11 +940,13 @@ class VectorContainerIterator : public BaseIter<ValuePtr, uint32_t> {
return cur;
}

bool operator==(VectorContainerIterator<ValueConstPtr> const& rhs) const {
return current_ == rhs.current_;
friend bool operator==(VectorContainerIterator const& lhs,
VectorContainerIterator const& rhs) {
return lhs.current_ == rhs.current_;
}
bool operator!=(VectorContainerIterator<ValueConstPtr> const& rhs) const {
return !(*this == rhs);
friend bool operator!=(VectorContainerIterator const& lhs,
VectorContainerIterator const& rhs) {
return !(lhs == rhs);
}

private:
Expand Down
13 changes: 13 additions & 0 deletions folly/container/detail/F14Table.h
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,19 @@ class F14Table : public Policy {
prefetchAddr(firstChunk);
return F14HashToken(std::move(hp));
}

// Prefetch the first matched value if there is at least one match in tags
template <typename K>
void prefetchFirstMatchedValue(K const& key) const {
auto hp = splitHash(this->computeKeyHash(key));
std::size_t index = hp.first;
ChunkPtr chunk = chunks_ + (index & chunkMask_);
auto hits = chunk->tagMatchIter(hp.second);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you observe any overhead from doing tagMatchIter twice for every key?

if (hits.hasNext()) {
auto i = hits.next();
this->prefetchValue(chunk->item(i));
}
}

template <typename K>
FOLLY_ALWAYS_INLINE ItemIter find(K const& key) const {
Expand Down
15 changes: 15 additions & 0 deletions folly/dynamic-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ struct dynamic::item_iterator : detail::IteratorAdaptor<
/* implicit */ item_iterator(dynamic::ObjectImpl::iterator b) : Super(b) {}

using object_type = dynamic::ObjectImpl;

using Super::operator==;
using Super::operator!=;
};

struct dynamic::value_iterator : detail::IteratorAdaptor<
Expand All @@ -256,6 +259,9 @@ struct dynamic::value_iterator : detail::IteratorAdaptor<
using object_type = dynamic::ObjectImpl;

dynamic& dereference() const { return base()->second; }

using Super::operator==;
using Super::operator!=;
};

struct dynamic::const_item_iterator
Expand All @@ -276,6 +282,9 @@ struct dynamic::const_item_iterator
/* implicit */ const_item_iterator(item_iterator i) : Super(i.base()) {}

using object_type = dynamic::ObjectImpl const;

using Super::operator==;
using Super::operator!=;
};

struct dynamic::const_key_iterator : detail::IteratorAdaptor<
Expand All @@ -294,6 +303,9 @@ struct dynamic::const_key_iterator : detail::IteratorAdaptor<
using object_type = dynamic::ObjectImpl const;

dynamic const& dereference() const { return base()->first; }

using Super::operator==;
using Super::operator!=;
};

struct dynamic::const_value_iterator : detail::IteratorAdaptor<
Expand All @@ -315,6 +327,9 @@ struct dynamic::const_value_iterator : detail::IteratorAdaptor<
using object_type = dynamic::ObjectImpl const;

dynamic const& dereference() const { return base()->second; }

using Super::operator==;
using Super::operator!=;
};

//////////////////////////////////////////////////////////////////////
Expand Down
87 changes: 75 additions & 12 deletions folly/experimental/symbolizer/Dwarf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,14 +458,18 @@ bool Dwarf::findDebugInfoOffset(
* Best effort:
* - fills @inlineFrames if mode == FULL_WITH_INLINE,
* - calls @eachParameterName on the function parameters.
*
* if @checkAddress is true, we verify that the address is mapped to
* a range in this CU before running the line number VM
*/
bool Dwarf::findLocation(
uintptr_t address,
const LocationInfoMode mode,
detail::CompilationUnit& cu,
LocationInfo& locationInfo,
folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(folly::StringPiece)> eachParameterName) const {
folly::FunctionRef<void(folly::StringPiece)> eachParameterName,
bool checkAddress) const {
detail::Die die = getDieAtOffset(cu, cu.firstDie);
// Partial compilation unit (DW_TAG_partial_unit) is not supported.
FOLLY_SAFE_CHECK(
Expand All @@ -477,41 +481,98 @@ bool Dwarf::findLocation(
folly::StringPiece compilationDirectory;
folly::Optional<folly::StringPiece> mainFileName;
folly::Optional<uint64_t> baseAddrCU;
folly::Optional<uint64_t> rangesOffset;
bool seenLowPC = false;
bool seenHighPC = false;
enum : unsigned {
kStmtList = 1U << 0,
kCompDir = 1U << 1,
kName = 1U << 2,
kLowPC = 1U << 3,
kHighPCOrRanges = 1U << 4,
};
unsigned expectedAttributes = kStmtList | kCompDir | kName | kLowPC;
bool foundAddress = !checkAddress;
if (!foundAddress) {
expectedAttributes |= kHighPCOrRanges;
}
forEachAttribute(cu, die, [&](const detail::Attribute& attr) {
switch (attr.spec.name) {
case DW_AT_stmt_list:
expectedAttributes &= ~kStmtList;
// Offset in .debug_line for the line number VM program for this
// compilation unit
lineOffset = boost::get<uint64_t>(attr.attrValue);
break;
case DW_AT_comp_dir:
expectedAttributes &= ~kCompDir;
// Compilation directory
compilationDirectory = boost::get<folly::StringPiece>(attr.attrValue);
break;
case DW_AT_name:
expectedAttributes &= ~kName;
// File name of main file being compiled
mainFileName = boost::get<folly::StringPiece>(attr.attrValue);
break;
case DW_AT_low_pc:
case DW_AT_entry_pc:
// 2.17.1: historically DW_AT_low_pc was used. DW_AT_entry_pc was
// introduced in DWARF3. Support either to determine the base address of
// the CU.
expectedAttributes &= ~kLowPC;
baseAddrCU = boost::get<uint64_t>(attr.attrValue);
if (!foundAddress) {
if (address < *baseAddrCU) {
return false;
}
seenLowPC = true;
if (seenHighPC) {
foundAddress = true;
} else if (rangesOffset) {
if (!isAddrInRangeList(address, baseAddrCU, *rangesOffset,
cu.addrSize)) {
return false;
}
foundAddress = true;
}
}
break;
case DW_AT_high_pc:
expectedAttributes &= ~kHighPCOrRanges;
if (!foundAddress) {
if (address >= boost::get<uint64_t>(attr.attrValue)) {
return false;
}
seenHighPC = true;
foundAddress = seenLowPC;
}
break;
case DW_AT_ranges:
// 3.1.1: CU entries have:
// - either DW_AT_low_pc and DW_AT_high_pc
// OR
// - DW_AT_ranges and optional DW_AT_low_pc
expectedAttributes &= ~kHighPCOrRanges;
if (!foundAddress) {
rangesOffset = boost::get<uint64_t>(attr.attrValue);
if (seenLowPC) {
if (!isAddrInRangeList(address, baseAddrCU, *rangesOffset,
cu.addrSize)) {
return false;
}
foundAddress = true;
}
}
break;
}
return true; // continue forEachAttribute
return (expectedAttributes != 0); // continue forEachAttribute
});

if (!foundAddress || !lineOffset) {
return false;
}

if (mainFileName) {
locationInfo.hasMainFile = true;
locationInfo.mainFile = Path(compilationDirectory, "", *mainFileName);
}

if (!lineOffset) {
return false;
}

folly::StringPiece lineSection(debugLine_);
lineSection.advance(*lineOffset);
LineNumberVM lineVM(lineSection, compilationDirectory);
Expand Down Expand Up @@ -660,7 +721,8 @@ bool Dwarf::findAddress(
// Read compilation unit header from .debug_info
auto unit = getCompilationUnit(debugInfo_, offset);
return findLocation(
address, mode, unit, locationInfo, inlineFrames, eachParameterName);
address, mode, unit, locationInfo, inlineFrames, eachParameterName,
false /*checkAddress*/);
} else if (mode == LocationInfoMode::FAST) {
// NOTE: Clang (when using -gdwarf-aranges) doesn't generate entries
// in .debug_aranges for some functions, but always generates
Expand Down Expand Up @@ -688,7 +750,8 @@ bool Dwarf::findAddress(
unit,
locationInfo,
inlineFrames,
eachParameterName)) {
eachParameterName,
true /*checkAddress*/)) {
return true;
}
}
Expand Down
6 changes: 5 additions & 1 deletion folly/experimental/symbolizer/Dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,18 @@ class Dwarf {
* Best effort:
* - fills @inlineFrames if mode == FULL_WITH_INLINE,
* - calls @eachParameterName on the function parameters.
*
* if @checkAddress is true, we verify that the address is mapped to
* a range in this CU before running the line number VM
*/
bool findLocation(
uintptr_t address,
const LocationInfoMode mode,
detail::CompilationUnit& cu,
LocationInfo& info,
folly::Range<SymbolizedFrame*> inlineFrames,
folly::FunctionRef<void(folly::StringPiece)> eachParameterName) const;
folly::FunctionRef<void(folly::StringPiece)> eachParameterName,
bool checkAddress = true) const;

/**
* Finds a subprogram debugging info entry that contains a given address among
Expand Down
9 changes: 5 additions & 4 deletions folly/experimental/symbolizer/SignalHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,10 +478,11 @@ void signalHandler(int signum, siginfo_t* info, void* uctx) {

#endif // FOLLY_USE_SYMBOLIZER

// Small sigaltstack size threshold.
// 8931 is known to cause the signal handler to stack overflow during
// symbolization even for a simple one-liner "kill(getpid(), SIGTERM)".
constexpr size_t kSmallSigAltStackSize = 8931;
// Small sigaltstack size threshold. If the alternate stack is too small we
// must use UnsafeSelfAllocateStackTracePrinter() to avoid stack overflow
// during symbolization of a signal. 48K has been observed to have stack
// overflow, and 56K has been observed to work.
constexpr size_t kSmallSigAltStackSize = 65536;

FOLLY_MAYBE_UNUSED bool isSmallSigAltStackEnabled() {
stack_t ss;
Expand Down
8 changes: 4 additions & 4 deletions folly/fibers/Fiber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Fiber::Fiber(FiberManager& fiberManager)
void Fiber::init(bool recordStackUsed) {
// It is necessary to disable the logic for ASAN because we change
// the fiber's stack.
#ifndef FOLLY_SANITIZE_ADDRESS
#ifndef FOLLY_LIBRARY_SANITIZE_ADDRESS
recordStackUsed_ = recordStackUsed;
if (UNLIKELY(recordStackUsed_ && !stackFilledWithMagic_)) {
CHECK_EQ(
Expand All @@ -103,7 +103,7 @@ void Fiber::init(bool recordStackUsed) {
}

Fiber::~Fiber() {
#ifdef FOLLY_SANITIZE_ADDRESS
#ifdef FOLLY_LIBRARY_SANITIZE_ADDRESS
if (asanFakeStack_ != nullptr) {
fiberManager_.freeFakeStack(asanFakeStack_);
}
Expand All @@ -115,7 +115,7 @@ Fiber::~Fiber() {
void Fiber::recordStackPosition() {
// For ASAN builds, functions may run on fake stack.
// So we cannot get meaningful stack position.
#ifndef FOLLY_SANITIZE_ADDRESS
#ifndef FOLLY_LIBRARY_SANITIZE_ADDRESS
int stackDummy;
auto currentPosition = static_cast<size_t>(
fiberStackLimit_ + fiberStackSize_ -
Expand All @@ -126,7 +126,7 @@ void Fiber::recordStackPosition() {
}

[[noreturn]] void Fiber::fiberFunc() {
#ifdef FOLLY_SANITIZE_ADDRESS
#ifdef FOLLY_LIBRARY_SANITIZE_ADDRESS
fiberManager_.registerFinishSwitchStackWithAsan(
nullptr, &asanMainStackBase_, &asanMainStackSize_);
#endif
Expand Down
2 changes: 1 addition & 1 deletion folly/fibers/Fiber.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ class Fiber {
folly::IntrusiveListHook globalListHook_; /**< list hook for global list */
std::thread::id threadId_{};

#ifdef FOLLY_SANITIZE_ADDRESS
#ifdef FOLLY_LIBRARY_SANITIZE_ADDRESS
void* asanFakeStack_{nullptr};
const void* asanMainStackBase_{nullptr};
size_t asanMainStackSize_{0};
Expand Down
6 changes: 3 additions & 3 deletions folly/fibers/FiberManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include <folly/portability/Unistd.h>
#include <folly/synchronization/SanitizeThread.h>

#ifdef FOLLY_SANITIZE_ADDRESS
#ifdef FOLLY_LIBRARY_SANITIZE_ADDRESS

#ifndef _WIN32
#include <dlfcn.h>
Expand Down Expand Up @@ -217,7 +217,7 @@ void FiberManager::FibersPoolResizer::run() {
}
}

#ifdef FOLLY_SANITIZE_ADDRESS
#ifdef FOLLY_LIBRARY_SANITIZE_ADDRESS

void FiberManager::registerStartSwitchStackWithAsan(
void** saveFakeStack,
Expand Down Expand Up @@ -336,7 +336,7 @@ static AsanUnpoisonMemoryRegionFuncPtr getUnpoisonMemoryRegionFunc() {
return nullptr;
}

#endif // FOLLY_SANITIZE_ADDRESS
#endif // FOLLY_LIBRARY_SANITIZE_ADDRESS

// TVOS and WatchOS platforms have SIGSTKSZ but not sigaltstack
#if defined(SIGSTKSZ) && !FOLLY_APPLE_TVOS && !FOLLY_APPLE_WATCHOS
Expand Down
Loading