uint64 Sampler::recordAllocationSample(const void* item, uint64 size, bool callback_ok) { AvmAssertMsg(sampling(), "How did we get here if sampling is disabled?"); if(!samplingNow) return 0; if(!samplingAllAllocs) return 0; if(!sampleSpaceCheck(callback_ok)) return 0; (void)item; lastAllocSample = currentSample; writeRawSample(NEW_AUX_SAMPLE); uint64 uid = allocId++; uids.add(item, (void*)uid); write(currentSample, uid); write(currentSample, item); write(currentSample, (uintptr)0); write(currentSample, size); AvmAssertMsg((uintptr)currentSample % 4 == 0, "Alignment should have occurred at end of raw sample.\n"); numSamples++; return uid; }
void Sampler::sample() { AvmAssertMsg(sampling(), "How did we get here if sampling is disabled?"); if(!samplingNow || !core->callStack || !sampleSpaceCheck()) return; writeRawSample(RAW_SAMPLE); numSamples++; }
void Sampler::recordDeallocationSample(const void* item, uint64 size) { AvmAssertMsg(sampling(), "How did we get here if sampling is disabled?"); AvmAssert(item != 0); // recordDeallocationSample doesn't honor the samplingNow flag // this is to avoid dropping deleted object samples when sampling is paused. uint64 uid = (uint64)uids.get(item); // If we didn't find a UID then this wasn't memory that the sampler knew was allocated if(uid && sampleSpaceCheck(false)) { // if( !uid ) // uid = (uint64)-1; writeRawSample(DELETED_OBJECT_SAMPLE); write(currentSample, uid); write(currentSample, size); numSamples++; AvmAssertMsg((uintptr)currentSample % 4 == 0, "Alignment should have occurred at end of raw sample.\n"); } // Nuke the ptr in the sample stream for the newobject sample if( samples ) { byte* oldptr = 0; if( (oldptr = (byte*)ptrSamples->get(item)) != 0 ) { #ifdef _DEBUG void* oldval = 0; read(oldptr, oldval); AvmAssertMsg(oldval==item, "Sample stream corrupt, dealloc doesn't point to correct address"); rewind(oldptr, sizeof(void*)); #endif write(oldptr, (void*)0); ptrSamples->remove(item); } } if(uid) uids.remove(item); }
void Sampler::sample() { AvmAssertMsg(sampling(), "How did we get here if sampling is disabled?"); if(!samplingNow) return; uint64_t nowMicros = this->nowMicros(); const uint64_t sampleFrequencyMicros = SAMPLE_FREQUENCY_MILLIS * 1000; if (takeSample) { if (core->callStack) { // We may want to write more than one sample. E.g. if 5.5 milliseconds have // passed, we'll write 5 samples. int sampleCount = 0; if (lastSampleCheckMicros != 0) sampleCount = (int) ((nowMicros - lastSampleCheckMicros) / sampleFrequencyMicros); if (sampleCount <= 0) sampleCount = 1; for (int sampleNum = sampleCount-1; sampleNum >= 0; sampleNum--) { if (!sampleSpaceCheck()) break; // We artificially manufacture a different time for each sample. uint64_t sampleTimeMicros = nowMicros - (sampleNum * sampleFrequencyMicros); writeRawSample(RAW_SAMPLE, sampleTimeMicros); numSamples++; } } } // Even if the callstack was empty, don't take another sample until the next timer tick. takeSample = 0; // Don't just set lastSampleCheckMicros equal to nowMicros -- we want to keep the // sampling frequency as close to one per millisecond as we can. uint64_t elapsed = nowMicros - lastSampleCheckMicros; lastSampleCheckMicros += (elapsed / sampleFrequencyMicros * sampleFrequencyMicros); }