2018-12-12 03:52:51 +01:00
|
|
|
#include <profiling.hpp>
|
|
|
|
|
2018-09-13 18:41:53 +02:00
|
|
|
#include <fstream>
|
2019-06-24 18:39:03 +02:00
|
|
|
#include <util/fs.hpp>
|
2018-09-13 18:41:53 +02:00
|
|
|
|
|
|
|
namespace llarp
|
|
|
|
{
|
|
|
|
bool
|
|
|
|
RouterProfile::BEncode(llarp_buffer_t* buf) const
|
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!bencode_start_dict(buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeWriteDictInt("g", connectGoodCount, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeWriteDictInt("p", pathSuccessCount, buf))
|
2018-09-14 16:50:37 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeWriteDictInt("s", pathFailCount, buf))
|
2018-09-14 16:50:37 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeWriteDictInt("t", connectTimeoutCount, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeWriteDictInt("u", lastUpdated.count(), buf))
|
2019-03-04 18:03:18 +01:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeWriteDictInt("v", version, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return bencode_end(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-02-03 00:12:42 +01:00
|
|
|
RouterProfile::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
|
|
|
bool read = false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeMaybeReadDictInt("g", connectGoodCount, read, k, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeMaybeReadDictInt("t", connectTimeoutCount, read, k, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeMaybeReadDictInt("u", lastUpdated, read, k, buf))
|
2019-03-04 18:03:18 +01:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeMaybeReadDictInt("v", version, read, k, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeMaybeReadDictInt("s", pathFailCount, read, k, buf))
|
2018-09-14 16:50:37 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BEncodeMaybeReadDictInt("p", pathSuccessCount, read, k, buf))
|
2018-09-14 16:50:37 +02:00
|
|
|
return false;
|
2018-09-13 18:41:53 +02:00
|
|
|
return read;
|
|
|
|
}
|
|
|
|
|
2019-03-04 18:03:18 +01:00
|
|
|
void
|
2019-03-05 14:38:50 +01:00
|
|
|
RouterProfile::Decay()
|
2019-03-04 18:03:18 +01:00
|
|
|
{
|
2019-03-05 14:38:50 +01:00
|
|
|
connectGoodCount /= 2;
|
|
|
|
connectTimeoutCount /= 2;
|
|
|
|
pathSuccessCount /= 2;
|
|
|
|
pathFailCount /= 2;
|
2019-04-16 19:30:07 +02:00
|
|
|
lastDecay = llarp::time_now_ms();
|
2019-03-04 18:03:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RouterProfile::Tick()
|
|
|
|
{
|
2019-04-16 19:27:35 +02:00
|
|
|
// 15 seconds
|
2020-02-24 20:40:45 +01:00
|
|
|
static constexpr auto updateInterval = 15s;
|
2020-04-07 20:38:56 +02:00
|
|
|
const auto now = llarp::time_now_ms();
|
|
|
|
if (lastDecay < now && now - lastDecay > updateInterval)
|
2019-03-05 14:38:50 +01:00
|
|
|
Decay();
|
2019-03-04 18:03:18 +01:00
|
|
|
}
|
|
|
|
|
2018-09-13 18:41:53 +02:00
|
|
|
bool
|
2018-09-14 16:50:37 +02:00
|
|
|
RouterProfile::IsGood(uint64_t chances) const
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (connectTimeoutCount > chances)
|
|
|
|
return connectTimeoutCount < connectGoodCount && (pathSuccessCount * chances) > pathFailCount;
|
2019-04-05 16:58:22 +02:00
|
|
|
return (pathSuccessCount * chances) > pathFailCount;
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
static bool constexpr checkIsGood(uint64_t fails, uint64_t success, uint64_t chances)
|
2019-04-16 13:44:55 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (fails > 0 && (fails + success) >= chances)
|
2019-04-17 16:46:00 +02:00
|
|
|
return (success / fails) > 1;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (success == 0)
|
2019-04-16 13:44:55 +02:00
|
|
|
return fails < chances;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
RouterProfile::IsGoodForConnect(uint64_t chances) const
|
|
|
|
{
|
|
|
|
return checkIsGood(connectTimeoutCount, connectGoodCount, chances);
|
|
|
|
}
|
2019-04-16 15:20:48 +02:00
|
|
|
|
2019-04-16 13:44:55 +02:00
|
|
|
bool
|
|
|
|
RouterProfile::IsGoodForPath(uint64_t chances) const
|
|
|
|
{
|
|
|
|
return checkIsGood(pathFailCount, pathSuccessCount, chances);
|
|
|
|
}
|
|
|
|
|
2019-05-24 04:01:36 +02:00
|
|
|
Profiling::Profiling() : m_DisableProfiling(false)
|
2019-04-25 13:00:18 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Profiling::Disable()
|
|
|
|
{
|
|
|
|
m_DisableProfiling.store(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Profiling::Enable()
|
|
|
|
{
|
|
|
|
m_DisableProfiling.store(false);
|
|
|
|
}
|
|
|
|
|
2019-04-16 13:44:55 +02:00
|
|
|
bool
|
2019-04-16 15:20:48 +02:00
|
|
|
Profiling::IsBadForConnect(const RouterID& r, uint64_t chances)
|
2019-04-16 13:44:55 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (m_DisableProfiling.load())
|
2019-04-25 13:00:18 +02:00
|
|
|
return false;
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2019-04-16 13:44:55 +02:00
|
|
|
auto itr = m_Profiles.find(r);
|
2020-04-07 20:38:56 +02:00
|
|
|
if (itr == m_Profiles.end())
|
2019-04-16 13:44:55 +02:00
|
|
|
return false;
|
|
|
|
return !itr->second.IsGoodForConnect(chances);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-04-16 15:20:48 +02:00
|
|
|
Profiling::IsBadForPath(const RouterID& r, uint64_t chances)
|
2019-04-16 13:44:55 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (m_DisableProfiling.load())
|
2019-04-25 13:00:18 +02:00
|
|
|
return false;
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2019-04-16 13:44:55 +02:00
|
|
|
auto itr = m_Profiles.find(r);
|
2020-04-07 20:38:56 +02:00
|
|
|
if (itr == m_Profiles.end())
|
2019-04-16 13:44:55 +02:00
|
|
|
return false;
|
|
|
|
return !itr->second.IsGoodForPath(chances);
|
|
|
|
}
|
|
|
|
|
2018-09-13 18:41:53 +02:00
|
|
|
bool
|
2018-09-14 16:50:37 +02:00
|
|
|
Profiling::IsBad(const RouterID& r, uint64_t chances)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (m_DisableProfiling.load())
|
2019-04-25 13:00:18 +02:00
|
|
|
return false;
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2018-09-13 18:41:53 +02:00
|
|
|
auto itr = m_Profiles.find(r);
|
2020-04-07 20:38:56 +02:00
|
|
|
if (itr == m_Profiles.end())
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2018-09-14 16:50:37 +02:00
|
|
|
return !itr->second.IsGood(chances);
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
|
2019-03-04 18:03:18 +01:00
|
|
|
void
|
|
|
|
Profiling::Tick()
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2020-04-07 20:38:56 +02:00
|
|
|
std::for_each(m_Profiles.begin(), m_Profiles.end(), [](auto& item) { item.second.Tick(); });
|
2019-03-04 18:03:18 +01:00
|
|
|
}
|
|
|
|
|
2018-09-13 18:41:53 +02:00
|
|
|
void
|
2019-04-17 16:46:00 +02:00
|
|
|
Profiling::MarkConnectTimeout(const RouterID& r)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2018-09-13 18:41:53 +02:00
|
|
|
m_Profiles[r].connectTimeoutCount += 1;
|
2019-03-04 18:03:18 +01:00
|
|
|
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-04-17 16:46:00 +02:00
|
|
|
Profiling::MarkConnectSuccess(const RouterID& r)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2018-09-13 18:41:53 +02:00
|
|
|
m_Profiles[r].connectGoodCount += 1;
|
2019-03-04 18:03:18 +01:00
|
|
|
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
|
2019-03-31 17:25:13 +02:00
|
|
|
void
|
|
|
|
Profiling::ClearProfile(const RouterID& r)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2019-03-31 17:25:13 +02:00
|
|
|
m_Profiles.erase(r);
|
|
|
|
}
|
|
|
|
|
2020-01-03 13:52:19 +01:00
|
|
|
void
|
|
|
|
Profiling::MarkHopFail(const RouterID& r)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2020-01-03 13:52:19 +01:00
|
|
|
m_Profiles[r].pathFailCount += 1;
|
|
|
|
m_Profiles[r].lastUpdated = llarp::time_now_ms();
|
|
|
|
}
|
|
|
|
|
2018-09-14 16:50:37 +02:00
|
|
|
void
|
|
|
|
Profiling::MarkPathFail(path::Path* p)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2019-05-07 14:31:34 +02:00
|
|
|
size_t idx = 0;
|
2020-04-07 20:38:56 +02:00
|
|
|
for (const auto& hop : p->hops)
|
2018-09-14 16:50:37 +02:00
|
|
|
{
|
2019-05-07 14:31:34 +02:00
|
|
|
// don't mark first hop as failure because we are connected to it directly
|
2020-04-07 20:38:56 +02:00
|
|
|
if (idx)
|
2019-05-07 14:31:34 +02:00
|
|
|
{
|
|
|
|
m_Profiles[hop.rc.pubkey].pathFailCount += 1;
|
|
|
|
m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms();
|
|
|
|
}
|
|
|
|
++idx;
|
2018-09-14 16:50:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Profiling::MarkPathSuccess(path::Path* p)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2019-03-25 16:41:37 +01:00
|
|
|
const auto sz = p->hops.size();
|
2020-04-07 20:38:56 +02:00
|
|
|
for (const auto& hop : p->hops)
|
2018-09-14 16:50:37 +02:00
|
|
|
{
|
2019-03-25 16:41:37 +01:00
|
|
|
m_Profiles[hop.rc.pubkey].pathSuccessCount += sz;
|
2019-03-04 18:03:18 +01:00
|
|
|
m_Profiles[hop.rc.pubkey].lastUpdated = llarp::time_now_ms();
|
2018-09-14 16:50:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-13 18:41:53 +02:00
|
|
|
bool
|
|
|
|
Profiling::Save(const char* fname)
|
|
|
|
{
|
2020-05-12 21:42:35 +02:00
|
|
|
std::shared_lock lock{m_ProfilesMutex};
|
2018-09-13 18:41:53 +02:00
|
|
|
size_t sz = (m_Profiles.size() * (RouterProfile::MaxSize + 32 + 8)) + 8;
|
|
|
|
|
2020-04-07 20:38:56 +02:00
|
|
|
std::vector<byte_t> tmp(sz, 0);
|
2019-02-03 00:12:42 +01:00
|
|
|
llarp_buffer_t buf(tmp);
|
2019-03-03 21:51:47 +01:00
|
|
|
auto res = BEncodeNoLock(&buf);
|
2020-04-07 20:38:56 +02:00
|
|
|
if (res)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
buf.sz = buf.cur - buf.base;
|
2019-06-24 18:39:03 +02:00
|
|
|
const fs::path fpath = std::string(fname);
|
2020-04-07 20:38:56 +02:00
|
|
|
auto optional_f = util::OpenFileStream<std::ofstream>(fpath, std::ios::binary);
|
|
|
|
if (!optional_f)
|
2019-06-24 18:39:03 +02:00
|
|
|
return false;
|
2020-05-20 21:46:08 +02:00
|
|
|
auto& f = *optional_f;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (f.is_open())
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
|
|
|
f.write((char*)buf.base, buf.sz);
|
2019-03-25 16:41:37 +01:00
|
|
|
m_LastSave = llarp::time_now_ms();
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Profiling::BEncode(llarp_buffer_t* buf) const
|
2019-03-03 21:51:47 +01:00
|
|
|
{
|
2020-05-12 21:42:35 +02:00
|
|
|
std::shared_lock lock{m_ProfilesMutex};
|
2019-03-03 21:51:47 +01:00
|
|
|
return BEncodeNoLock(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Profiling::BEncodeNoLock(llarp_buffer_t* buf) const
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!bencode_start_dict(buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2019-03-03 21:51:47 +01:00
|
|
|
|
2018-09-13 18:41:53 +02:00
|
|
|
auto itr = m_Profiles.begin();
|
2020-04-07 20:38:56 +02:00
|
|
|
while (itr != m_Profiles.end())
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!itr->first.BEncode(buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!itr->second.BEncode(buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
return bencode_end(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2019-02-03 00:12:42 +01:00
|
|
|
Profiling::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf)
|
2018-09-13 18:41:53 +02:00
|
|
|
{
|
2020-04-07 20:38:56 +02:00
|
|
|
if (k.sz != 32)
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
|
|
|
RouterProfile profile;
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!bencode_decode_dict(profile, buf))
|
2018-09-13 18:41:53 +02:00
|
|
|
return false;
|
|
|
|
RouterID pk = k.base;
|
2019-02-18 11:35:16 +01:00
|
|
|
return m_Profiles.emplace(pk, profile).second;
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
Profiling::Load(const char* fname)
|
|
|
|
{
|
De-abseil, part 2: mutex, locks, (most) time
- util::Mutex is now a std::shared_timed_mutex, which is capable of
exclusive and shared locks.
- util::Lock is still present as a std::lock_guard<util::Mutex>.
- the locking annotations are preserved, but updated to the latest
supported by clang rather than using abseil's older/deprecated ones.
- ACQUIRE_LOCK macro is gone since we don't pass mutexes by pointer into
locks anymore (WTF abseil).
- ReleasableLock is gone. Instead there are now some llarp::util helper
methods to obtain unique and/or shared locks:
- `auto lock = util::unique_lock(mutex);` gets an RAII-but-also
unlockable object (std::unique_lock<T>, with T inferred from
`mutex`).
- `auto lock = util::shared_lock(mutex);` gets an RAII shared (i.e.
"reader") lock of the mutex.
- `auto lock = util::unique_locks(mutex1, mutex2, mutex3);` can be
used to atomically lock multiple mutexes at once (returning a
tuple of the locks).
This are templated on the mutex which makes them a bit more flexible
than using a concrete type: they can be used for any type of lockable
mutex, not only util::Mutex. (Some of the code here uses them for
getting locks around a std::mutex). Until C++17, using the RAII types
is painfully verbose:
```C++
// pre-C++17 - needing to figure out the mutex type here is annoying:
std::unique_lock<util::Mutex> lock(mutex);
// pre-C++17 and even more verbose (but at least the type isn't needed):
std::unique_lock<decltype(mutex)> lock(mutex);
// our compromise:
auto lock = util::unique_lock(mutex);
// C++17:
std::unique_lock lock(mutex);
```
All of these functions will also warn (under gcc or clang) if you
discard the return value. You can also do fancy things like
`auto l = util::unique_lock(mutex, std::adopt_lock)` (which lets a
lock take over an already-locked mutex).
- metrics code is gone, which also removes a big pile of code that was
only used by metrics:
- llarp::util::Scheduler
- llarp::thread::TimerQueue
- llarp::util::Stopwatch
2020-02-21 18:21:11 +01:00
|
|
|
util::Lock lock(m_ProfilesMutex);
|
2018-09-13 18:41:53 +02:00
|
|
|
m_Profiles.clear();
|
2020-04-07 20:38:56 +02:00
|
|
|
if (!BDecodeReadFromFile(fname, *this))
|
2018-09-15 13:37:46 +02:00
|
|
|
{
|
|
|
|
llarp::LogWarn("failed to load router profiles from ", fname);
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-12 14:05:43 +02:00
|
|
|
m_LastSave = llarp::time_now_ms();
|
2018-09-15 13:37:46 +02:00
|
|
|
return true;
|
2018-09-13 18:41:53 +02:00
|
|
|
}
|
|
|
|
|
2019-03-25 16:41:37 +01:00
|
|
|
bool
|
|
|
|
Profiling::ShouldSave(llarp_time_t now) const
|
|
|
|
{
|
|
|
|
auto dlt = now - m_LastSave;
|
2020-02-24 20:40:45 +01:00
|
|
|
return dlt > 1min;
|
2019-03-25 16:41:37 +01:00
|
|
|
}
|
2018-09-13 18:41:53 +02:00
|
|
|
} // namespace llarp
|