Skip to content

Commit 6a128e0

Browse files
committed
buffer: report proper retained size in profiler
Make buffers report the proper retained size in heap snapshots. Before this commit, Buffer objects would show up in the heap profiler as being only a few hundred bytes large, even if the actual buffer was many megabytes.
1 parent 87518f1 commit 6a128e0

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

src/node_buffer.cc

+61-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "node_buffer.h"
2525

2626
#include "v8.h"
27+
#include "v8-profiler.h"
2728

2829
#include <assert.h>
2930
#include <stdlib.h> // malloc, free
@@ -33,9 +34,10 @@
3334
# include <arpa/inet.h> // htons, htonl
3435
#endif
3536

36-
3737
#define MIN(a,b) ((a) < (b) ? (a) : (b))
3838

39+
#define BUFFER_CLASS_ID (0xBABE)
40+
3941
namespace node {
4042

4143
using namespace v8;
@@ -188,6 +190,7 @@ Buffer::Buffer(Handle<Object> wrapper, size_t length) : ObjectWrap() {
188190

189191
length_ = 0;
190192
callback_ = NULL;
193+
handle_.SetWrapperClassId(BUFFER_CLASS_ID);
191194

192195
Replace(NULL, length, NULL, NULL);
193196
}
@@ -728,6 +731,61 @@ bool Buffer::HasInstance(v8::Handle<v8::Value> val) {
728731
}
729732

730733

734+
class RetainedBufferInfo: public v8::RetainedObjectInfo {
735+
public:
736+
RetainedBufferInfo(Buffer* buffer);
737+
virtual void Dispose();
738+
virtual bool IsEquivalent(RetainedObjectInfo* other);
739+
virtual intptr_t GetHash();
740+
virtual const char* GetLabel();
741+
virtual intptr_t GetSizeInBytes();
742+
private:
743+
Buffer* buffer_;
744+
static const char label[];
745+
};
746+
747+
const char RetainedBufferInfo::label[] = "Buffer";
748+
749+
750+
RetainedBufferInfo::RetainedBufferInfo(Buffer* buffer): buffer_(buffer) {
751+
}
752+
753+
754+
void RetainedBufferInfo::Dispose() {
755+
buffer_ = NULL;
756+
delete this;
757+
}
758+
759+
760+
bool RetainedBufferInfo::IsEquivalent(RetainedObjectInfo* other) {
761+
return label == other->GetLabel() &&
762+
buffer_ == static_cast<RetainedBufferInfo*>(other)->buffer_;
763+
}
764+
765+
766+
intptr_t RetainedBufferInfo::GetHash() {
767+
return reinterpret_cast<intptr_t>(buffer_);
768+
}
769+
770+
771+
const char* RetainedBufferInfo::GetLabel() {
772+
return label;
773+
}
774+
775+
776+
intptr_t RetainedBufferInfo::GetSizeInBytes() {
777+
return Buffer::Length(buffer_);
778+
}
779+
780+
781+
RetainedObjectInfo* WrapperInfo(uint16_t class_id, Handle<Value> wrapper) {
782+
assert(class_id == BUFFER_CLASS_ID);
783+
assert(Buffer::HasInstance(wrapper));
784+
Buffer* buffer = Buffer::Unwrap<Buffer>(wrapper.As<Object>());
785+
return new RetainedBufferInfo(buffer);
786+
}
787+
788+
731789
void Buffer::Initialize(Handle<Object> target) {
732790
HandleScope scope;
733791

@@ -775,6 +833,8 @@ void Buffer::Initialize(Handle<Object> target) {
775833
Buffer::MakeFastBuffer);
776834

777835
target->Set(String::NewSymbol("SlowBuffer"), constructor_template->GetFunction());
836+
837+
HeapProfiler::DefineWrapperClass(BUFFER_CLASS_ID, WrapperInfo);
778838
}
779839

780840

0 commit comments

Comments
 (0)