mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:45:06 +00:00
8caeaf7a6c
This CL introduces new embedding APIs for supporting heap sample profiling. A registered sampling callback is invoked approximately every N bytes based on an exponential distribution, providing information about the isolate group the allocation occurred in, the user visible name of the allocated object type, a weak persistent handle to the allocated object, and the size of the allocation. Sampling is triggered using artificial TLAB boundaries to cause allocations to be sampled to take the allocation slow path where the registered callback can be invoked with the allocation information. Only new space allocations are currently traced, with old space allocation support to be added in a future CL. TEST=Dart_HeapSampling Change-Id: I22bcdeec6e823bc1ab44898d4c596fbed7169fa1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264520 Commit-Queue: Ben Konyi <bkonyi@google.com> Reviewed-by: Siva Annamalai <asiva@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
108 lines
2.8 KiB
C++
108 lines
2.8 KiB
C++
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "vm/random.h"
|
|
#include "vm/dart.h"
|
|
#include "vm/flags.h"
|
|
#include "vm/os.h"
|
|
|
|
namespace dart {
|
|
|
|
DEFINE_FLAG(uint64_t,
|
|
random_seed,
|
|
0,
|
|
"Override the random seed for debugging.");
|
|
|
|
Random::Random() {
|
|
uint64_t seed = FLAG_random_seed;
|
|
if (seed == 0) {
|
|
Dart_EntropySource callback = Dart::entropy_source_callback();
|
|
if (callback != NULL) {
|
|
if (!callback(reinterpret_cast<uint8_t*>(&seed), sizeof(seed))) {
|
|
// Callback failed. Reset the seed to 0.
|
|
seed = 0;
|
|
}
|
|
}
|
|
}
|
|
if (seed == 0) {
|
|
// We did not get a seed so far. As a fallback we do use the current time.
|
|
seed = OS::GetCurrentTimeMicros();
|
|
}
|
|
Initialize(seed);
|
|
}
|
|
|
|
void Random::Initialize(uint64_t seed) {
|
|
ASSERT(seed != 0);
|
|
// Crank the next state a couple of times.
|
|
_state = seed;
|
|
NextState();
|
|
NextState();
|
|
NextState();
|
|
NextState();
|
|
}
|
|
|
|
Random::Random(uint64_t seed) {
|
|
Initialize(seed);
|
|
}
|
|
|
|
Random::~Random() {
|
|
// Nothing to be done here.
|
|
}
|
|
|
|
// The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32.
|
|
// http://en.wikipedia.org/wiki/Multiply-with-carry
|
|
// The constant A is selected from "Numerical Recipes 3rd Edition" p.348 B1.
|
|
uint64_t Random::NextState() {
|
|
const uint64_t MASK_32 = 0xffffffff;
|
|
const uint64_t A = 0xffffda61;
|
|
|
|
uint64_t old_state = _state;
|
|
while (true) {
|
|
const uint64_t state_lo = old_state & MASK_32;
|
|
const uint64_t state_hi = (old_state >> 32) & MASK_32;
|
|
const uint64_t new_state = (A * state_lo) + state_hi;
|
|
if (_state.compare_exchange_weak(old_state, new_state,
|
|
std::memory_order_relaxed,
|
|
std::memory_order_relaxed)) {
|
|
return new_state;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t Random::NextUInt32() {
|
|
const uint64_t MASK_32 = 0xffffffff;
|
|
return static_cast<uint32_t>(NextState() & MASK_32);
|
|
}
|
|
|
|
static Random* global_random = nullptr;
|
|
static Mutex* global_random_mutex = nullptr;
|
|
|
|
void Random::Init() {
|
|
ASSERT(global_random_mutex == nullptr);
|
|
global_random_mutex = new Mutex(NOT_IN_PRODUCT("global_random_mutex"));
|
|
ASSERT(global_random == nullptr);
|
|
global_random = new Random();
|
|
}
|
|
|
|
void Random::Cleanup() {
|
|
delete global_random_mutex;
|
|
global_random_mutex = nullptr;
|
|
delete global_random;
|
|
global_random = nullptr;
|
|
}
|
|
|
|
uint64_t Random::GlobalNextUInt64() {
|
|
MutexLocker locker(global_random_mutex);
|
|
return global_random->NextUInt64();
|
|
}
|
|
|
|
double Random::NextDouble() {
|
|
uint64_t mantissa = NextUInt64() & 0xFFFFFFFFFFFFF;
|
|
// The exponent value 0 in biased form.
|
|
const uint64_t exp = 1023;
|
|
return bit_cast<double>(exp << 52 | mantissa) - 1.0;
|
|
}
|
|
|
|
} // namespace dart
|