Skip to content

Commit

Permalink
Merge pull request #9 from hyj1991/distance
Browse files Browse the repository at this point in the history
add: node distance
  • Loading branch information
hyj1991 authored Apr 19, 2018
2 parents 80bb36e + 8a0d2c4 commit 089ffd9
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/memory/edge.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SnapshotParser;
namespace snapshot_edge {
using nlohmann::json;

enum edge_types {
enum EdgeTypes {
KCONTEXTVARIABLE,
KELEMENT,
KPROPERTY,
Expand Down
2 changes: 1 addition & 1 deletion src/memory/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class SnapshotParser;
namespace snapshot_node {
using nlohmann::json;

enum node_types {
enum NodeTypes {
KHIDDEN,
KARRAY,
KSTRING,
Expand Down
3 changes: 3 additions & 0 deletions src/memory/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ void Parser::Parse(const Nan::FunctionCallbackInfo<Value>& info) {
if(strcmp(*mode, mode_search.c_str()) == 0) {
parser->snapshotParser->CreateAddressMap();
parser->snapshotParser->BuildTotalRetainer();
parser->snapshotParser->BuildDistances();
}
}
}
Expand All @@ -92,6 +93,8 @@ Local<Object> Parser::GetNodeById_(long id, int current, int limit, GetNodeTypes
node->Set(Nan::New<String>("address").ToLocalChecked(), Nan::New<String>(address).ToLocalChecked());
long self_size = snapshotParser->node_util->GetSelfSize(id, false);
node->Set(Nan::New<String>("self_size").ToLocalChecked(), Nan::New<Number>(self_size));
int distance = snapshotParser->GetDistance(id);
node->Set(Nan::New<String>("distance").ToLocalChecked(), Nan::New<Number>(distance));
// get edges
if(get_node_type == KALL || get_node_type == KEDGES) {
long* edges_local = snapshotParser->node_util->GetEdges(id, false);
Expand Down
152 changes: 152 additions & 0 deletions src/memory/snapshot_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,156 @@ long* SnapshotParser::GetRetainers(long id) {
}
return retainers;
}

void SnapshotParser::EnqueueNode_(snapshot_distance_t* t) {
if(t->node_distances_[t->ordinal] != NO_DISTANCE)
return;
t->node_distances_[t->ordinal] = t->distance;
t->node_to_visit[*(t->node_to_visit_length)] = t->ordinal;
*(t->node_to_visit_length) += 1;
}

bool SnapshotParser::Filter(long ordinal, long edge) {
int node_type = node_util->GetTypeForInt(ordinal, false);
if(node_type == snapshot_node::NodeTypes::KHIDDEN) {
std::string edge_name = edge_util->GetNameOrIndex(edge, true);
std::string node_name = node_util->GetName(ordinal, false);
std::string slow_function_map_name = "sloppy_function_map";
std::string native_context = "system / NativeContext";
return (strcmp(edge_name.c_str(), slow_function_map_name.c_str()) != 0) || (strcmp(node_name.c_str(), native_context.c_str()) != 0);
}
if(node_type == snapshot_node::NodeTypes::KARRAY) {
std::string node_name = node_util->GetName(ordinal, false);
std::string map_descriptors_name = "(map descriptors)";
if(strcmp(node_name.c_str(), map_descriptors_name.c_str()) != 0)
return true;
std::string edge_name = edge_util->GetNameOrIndex(edge, true);
int index = atoi(edge_name.c_str());
return index < 2 || (index % 3) != 1;
}
return true;
}

void SnapshotParser::ForEachRoot_(void (*action)(snapshot_distance_t* t), snapshot_distance_t* user_root, bool user_root_only) {
std::unordered_map<long, bool> visit_nodes;
long gc_roots = -1;
long* edges = node_util->GetEdges(root_index, false);
int length = node_util->GetEdgeCount(root_index, false);
for(int i = 0; i < length; i++) {
long target_node = edge_util->GetTargetNode(*(edges + i), true);
std::string node_name = node_util->GetName(target_node, false);
std::string gc_root_name = "(GC roots)";
if(strcmp(node_name.c_str(), gc_root_name.c_str()) == 0) {
gc_roots = target_node;
}
}
if(gc_roots == -1)
return;
if(user_root_only) {
// iterator the "true" root
for(int i = 0; i < length; i++) {
long target_node = edge_util->GetTargetNode(*(edges + i), true);
std::string node_name = node_util->GetName(target_node, false);
int type = node_util->GetTypeForInt(target_node, false);
// type != synthetic, means user root
if(type != snapshot_node::NodeTypes::KSYNTHETIC) {
if(visit_nodes.count(target_node) == 0) {
user_root->ordinal = target_node;
action(user_root);
visit_nodes.insert(std::unordered_map<long, bool>::value_type(target_node, true));
}
}
}
} else {
long* sub_root_edges = node_util->GetEdges(gc_roots, false);
int sub_root_edge_length = node_util->GetEdgeCount(gc_roots, false);
for(int i = 0; i < sub_root_edge_length; i++) {
long sub_root_ordinal = edge_util->GetTargetNode(*(sub_root_edges + i), true);
long* sub2_root_edges = node_util->GetEdges(sub_root_ordinal, false);
int sub2_root_edge_length = node_util->GetEdgeCount(sub_root_ordinal, false);
for(int j = 0; j < sub2_root_edge_length; j++) {
long sub2_root_ordinal = edge_util->GetTargetNode(*(sub2_root_edges + j), true);
// mark sub sub gc roots
if(visit_nodes.count(sub2_root_ordinal) == 0) {
user_root->ordinal = sub2_root_ordinal;
action(user_root);
visit_nodes.insert(std::unordered_map<long, bool>::value_type(sub2_root_ordinal, true));
}
}
// mark sub gc roots
if(visit_nodes.count(sub_root_ordinal) == 0) {
user_root->ordinal = sub_root_ordinal;
action(user_root);
visit_nodes.insert(std::unordered_map<long, bool>::value_type(sub_root_ordinal, true));
}
}
// mark sub roots
for(int i = 0; i < length; i++) {
long target_node = edge_util->GetTargetNode(*(edges + i), true);
if(visit_nodes.count(target_node) == 0) {
user_root->ordinal = target_node;
action(user_root);
visit_nodes.insert(std::unordered_map<long, bool>::value_type(target_node, true));
}
}
}
}

void SnapshotParser::BFS_(long* node_to_visit, int node_to_visit_length) {
int index = 0;
int temp = 0;
while(index < node_to_visit_length) {
long ordinal = node_to_visit[index++];
int distance = node_distances_[ordinal] + 1;
long* edges = node_util->GetEdges(ordinal, false);
int edge_length = node_util->GetEdgeCount(ordinal, false);
for(int i = 0; i < edge_length; i++) {
int edge_type = edge_util->GetTypeForInt(*(edges + i), true);
// ignore weak edge
if(edge_type == snapshot_edge::EdgeTypes::KWEAK)
continue;
int child_ordinal = edge_util->GetTargetNode(*(edges + i), true);
if(node_distances_[child_ordinal] != NO_DISTANCE)
continue;
// need optimized filter
// if(!Filter(ordinal, *(edges + i)))
// continue;
node_distances_[child_ordinal] = distance;
node_to_visit[node_to_visit_length++] = child_ordinal;
temp++;
}
}
if (node_to_visit_length > node_count) {
std::string error = "BFS failed. Nodes to visit (" + std::to_string(node_to_visit_length)
+ ") is more than nodes count (" + std::to_string(node_count) + ")";
Nan::ThrowTypeError(Nan::New<v8::String>(error).ToLocalChecked());
}
}

void SnapshotParser::BuildDistances() {
node_distances_ = new int[node_count];
for(long i = 0; i < node_count; i++) {
*(node_distances_ + i) = NO_DISTANCE;
}
long* node_to_visit = new long[node_count] {0};
int node_to_visit_length = 0;
// add user root
snapshot_distance_t* user_root = new snapshot_distance_t;
user_root->distance = 1;
user_root->node_to_visit = node_to_visit;
user_root->node_to_visit_length = &node_to_visit_length;
user_root->node_distances_ = node_distances_;
ForEachRoot_(EnqueueNode_, user_root, true);
BFS_(node_to_visit, node_to_visit_length);
// add rest
node_to_visit_length = 0;
user_root->distance = BASE_SYSTEMDISTANCE;
ForEachRoot_(EnqueueNode_, user_root, false);
BFS_(node_to_visit, node_to_visit_length);
user_root = nullptr;
}

int SnapshotParser::GetDistance(long id) {
return node_distances_[id];
}
}
17 changes: 17 additions & 0 deletions src/memory/snapshot_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@
namespace snapshot_parser {
using nlohmann::json;

typedef struct {
int distance;
long ordinal;
long* node_to_visit;
int* node_to_visit_length;
int* node_distances_;
} snapshot_distance_t;
typedef std::unordered_map<long, long> AddressMap;

const int NO_DISTANCE = -5;
const int BASE_SYSTEMDISTANCE = 100000000;

class SnapshotParser {
public:
explicit SnapshotParser(json profile);
Expand All @@ -23,6 +33,8 @@ class SnapshotParser {
void BuildTotalRetainer();
int GetRetainersCount(long id);
long* GetRetainers(long id);
void BuildDistances();
int GetDistance(long id);
static int IndexOf(json array, std::string target);
json nodes;
json edges;
Expand Down Expand Up @@ -51,12 +63,17 @@ class SnapshotParser {

private:
long* GetFirstEdgeIndexes();
static void EnqueueNode_(snapshot_distance_t* t);
void ForEachRoot_(void (*action)(snapshot_distance_t* t), snapshot_distance_t* user_root, bool user_root_only);
void BFS_(long* node_to_visit, int node_to_visit_length);
bool Filter(long ordinal, long edge);
// address -> node ordinal id
AddressMap address_map_;
// total retainers
long* retaining_nodes_;
long* retaining_edges_;
long* first_retainer_index_;
int* node_distances_;
};
}

Expand Down
3 changes: 2 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ function getNode() {

// getNode();

require('..').snapshot(snapshot).listen(3001);
console.time('cost');
require('..').snapshot(snapshot).listen(3001, () => console.timeEnd('cost'));
2 changes: 1 addition & 1 deletion worker/public/js/dashboard/component/tree_edges.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
raw.key = `${Math.random().toString(36).substr(2)}`;
raw.name = data.name;
raw.address = data.address;
raw.additional = `(type: ${data.type}, self_size: ${this.formatSize(data.self_size)})`;
raw.additional = `(type: ${data.type}, self_size: ${this.formatSize(data.self_size)}, distance: ${data.distance})`;
raw.edges = data.edges;
raw.edgesEnd = data.edges_end;
raw.edgesCurrent = data.edges_current;
Expand Down
2 changes: 1 addition & 1 deletion worker/public/js/dashboard/component/tree_retainers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
raw.key = `${Math.random().toString(36).substr(2)}`;
raw.name = data.name;
raw.address = data.address;
raw.additional = `(type: ${data.type}, self_size: ${this.formatSize(data.self_size)})`;
raw.additional = `(type: ${data.type}, self_size: ${this.formatSize(data.self_size)}, distance: ${data.distance})`;
raw.retainers = data.retainers;
raw.retainersEnd = data.retainers_end;
raw.retainersCurrent = data.retainers_current;
Expand Down

0 comments on commit 089ffd9

Please sign in to comment.