Caching function list and only sending deltas.

This commit is contained in:
Ben Vanik 2013-12-25 07:00:42 -08:00
parent 1c9fb97b5e
commit d368e0cb74
4 changed files with 90 additions and 43 deletions

View File

@ -64,6 +64,7 @@ module.service('DataSource', function($q) {
this.cache_ = { this.cache_ = {
modules: {}, modules: {},
moduleFunctionLists: {},
functions: {} functions: {}
}; };
}; };
@ -104,10 +105,29 @@ module.service('DataSource', function($q) {
}; };
DataSource.prototype.getFunctionList = function(moduleName) { DataSource.prototype.getFunctionList = function(moduleName) {
return this.issue({ var d = $q.defer();
var cached = this.cache_.moduleFunctionLists[moduleName];
this.issue({
command: 'cpu.get_function_list', command: 'cpu.get_function_list',
module: moduleName module: moduleName,
}); since: cached ? cached.version : 0
}).then((function(result) {
if (cached) {
cached.version = result.version;
for (var n = 0; n < result.list.length; n++) {
cached.list.push(result.list[n]);
}
} else {
cached = this.cache_.moduleFunctionLists[moduleName] = {
version: result.version,
list: result.list
};
}
d.resolve(cached.list);
}).bind(this), (function(e) {
d.reject(e);
}).bind(this));
return d.promise;
}; };
DataSource.prototype.getFunction = function(address) { DataSource.prototype.getFunction = function(address) {

View File

@ -97,6 +97,7 @@ SymbolInfo::Status Module::DeclareSymbol(
break; break;
} }
map_[address] = symbol_info; map_[address] = symbol_info;
list_.push_back(symbol_info);
status = SymbolInfo::STATUS_NEW; status = SymbolInfo::STATUS_NEW;
} }
UnlockMutex(lock_); UnlockMutex(lock_);
@ -160,10 +161,25 @@ SymbolInfo::Status Module::DefineVariable(VariableInfo* symbol_info) {
void Module::ForEachFunction(std::function<void (FunctionInfo*)> callback) { void Module::ForEachFunction(std::function<void (FunctionInfo*)> callback) {
LockMutex(lock_); LockMutex(lock_);
for (SymbolMap::iterator it = map_.begin(); for (auto it = list_.begin(); it != list_.end(); ++it) {
it != map_.end(); ++it) { SymbolInfo* symbol_info = *it;
if (it->second->type() == SymbolInfo::TYPE_FUNCTION) { if (symbol_info->type() == SymbolInfo::TYPE_FUNCTION) {
FunctionInfo* info = (FunctionInfo*)it->second; FunctionInfo* info = (FunctionInfo*)symbol_info;
callback(info);
}
}
UnlockMutex(lock_);
}
void Module::ForEachFunction(size_t since, size_t& version,
std::function<void (FunctionInfo*)> callback) {
LockMutex(lock_);
size_t count = list_.size();
version = count;
for (size_t n = since; n < count; n++) {
SymbolInfo* symbol_info = list_[n];
if (symbol_info->type() == SymbolInfo::TYPE_FUNCTION) {
FunctionInfo* info = (FunctionInfo*)symbol_info;
callback(info); callback(info);
} }
} }

View File

@ -45,6 +45,8 @@ public:
SymbolInfo::Status DefineVariable(VariableInfo* symbol_info); SymbolInfo::Status DefineVariable(VariableInfo* symbol_info);
void ForEachFunction(std::function<void (FunctionInfo*)> callback); void ForEachFunction(std::function<void (FunctionInfo*)> callback);
void ForEachFunction(size_t since, size_t& version,
std::function<void (FunctionInfo*)> callback);
int ReadMap(const char* file_name); int ReadMap(const char* file_name);
@ -62,6 +64,8 @@ private:
Mutex* lock_; Mutex* lock_;
typedef std::tr1::unordered_map<uint64_t, SymbolInfo*> SymbolMap; typedef std::tr1::unordered_map<uint64_t, SymbolInfo*> SymbolMap;
SymbolMap map_; SymbolMap map_;
typedef std::vector<SymbolInfo*> SymbolList;
SymbolList list_;
}; };

View File

@ -225,6 +225,32 @@ void Processor::OnDebugClientDisconnected(uint32_t client_id) {
runtime_->debugger()->ResumeAllThreads(true); runtime_->debugger()->ResumeAllThreads(true);
} }
json_t* json_object_set_string_new(
json_t* object, const char* key, const char* value) {
json_t* value_json = json_string(value);
json_object_set_new(object, key, value_json);
return value_json;
}
json_t* json_object_set_string_format_new(
json_t* object, const char* key, const char* format, ...) {
char buffer[1024];
va_list args;
va_start(args, format);
xevsnprintfa(buffer, XECOUNT(buffer), format, args);
va_end(args);
json_t* value_json = json_string(buffer);
json_object_set_new(object, key, value_json);
return value_json;
}
json_t* json_object_set_integer_new(
json_t* object, const char* key, json_int_t value) {
json_t* value_json = json_integer(value);
json_object_set_new(object, key, value_json);
return value_json;
}
json_t* Processor::OnDebugRequest( json_t* Processor::OnDebugRequest(
uint32_t client_id, const char* command, json_t* request, uint32_t client_id, const char* command, json_t* request,
bool& succeeded) { bool& succeeded) {
@ -240,8 +266,7 @@ json_t* Processor::OnDebugRequest(
for (auto it = modules.begin(); it != modules.end(); ++it) { for (auto it = modules.begin(); it != modules.end(); ++it) {
XexModule* module = (XexModule*)(*it); XexModule* module = (XexModule*)(*it);
json_t* module_json = json_object(); json_t* module_json = json_object();
json_t* module_name_json = json_string(module->name()); json_object_set_string_new(module_json, "name", module->name());
json_object_set_new(module_json, "name", module_name_json);
json_array_append_new(list, module_json); json_array_append_new(list, module_json);
} }
return list; return list;
@ -270,8 +295,16 @@ json_t* Processor::OnDebugRequest(
succeeded = false; succeeded = false;
return json_string("Module not found"); return json_string("Module not found");
} }
json_t* since_json = json_object_get(request, "since");
if (since_json && !json_is_number(since_json)) {
succeeded = false;
return json_string("Version since is an invalid type");
}
size_t since = since_json ?
(size_t)json_number_value(since_json) : 0;
json_t* list = json_array(); json_t* list = json_array();
module->ForEachFunction([&](FunctionInfo* info) { size_t version = 0;
module->ForEachFunction(since, version, [&](FunctionInfo* info) {
json_t* fn_json = json_object(); json_t* fn_json = json_object();
const char* name = info->name(); const char* name = info->name();
char name_buffer[32]; char name_buffer[32];
@ -280,15 +313,15 @@ json_t* Processor::OnDebugRequest(
info->address()); info->address());
name = name_buffer; name = name_buffer;
} }
json_t* name_json = json_string(name); json_object_set_string_new(fn_json, "name", name);
json_object_set_new(fn_json, "name", name_json); json_object_set_integer_new(fn_json, "address", info->address());
json_t* address_json = json_integer(info->address()); json_object_set_integer_new(fn_json, "linkStatus", info->status());
json_object_set_new(fn_json, "address", address_json);
json_t* link_status_json = json_integer(info->status());
json_object_set_new(fn_json, "linkStatus", link_status_json);
json_array_append_new(list, fn_json); json_array_append_new(list, fn_json);
}); });
return list; json_t* result = json_object();
json_object_set_integer_new(result, "version", version);
json_object_set_new(result, "list", list);
return result;
} else if (xestrcmpa(command, "get_function") == 0) { } else if (xestrcmpa(command, "get_function") == 0) {
json_t* address_json = json_object_get(request, "address"); json_t* address_json = json_object_get(request, "address");
if (!address_json || !json_is_number(address_json)) { if (!address_json || !json_is_number(address_json)) {
@ -397,32 +430,6 @@ json_t* Processor::OnDebugRequest(
} }
} }
json_t* json_object_set_string_new(
json_t* object, const char* key, const char* value) {
json_t* value_json = json_string(value);
json_object_set_new(object, key, value_json);
return value_json;
}
json_t* json_object_set_string_format_new(
json_t* object, const char* key, const char* format, ...) {
char buffer[1024];
va_list args;
va_start(args, format);
xevsnprintfa(buffer, XECOUNT(buffer), format, args);
va_end(args);
json_t* value_json = json_string(buffer);
json_object_set_new(object, key, value_json);
return value_json;
}
json_t* json_object_set_integer_new(
json_t* object, const char* key, json_int_t value) {
json_t* value_json = json_integer(value);
json_object_set_new(object, key, value_json);
return value_json;
}
json_t* Processor::DumpModule(XexModule* module, bool& succeeded) { json_t* Processor::DumpModule(XexModule* module, bool& succeeded) {
auto xex = module->xex(); auto xex = module->xex();
auto header = xe_xex2_get_header(xex); auto header = xe_xex2_get_header(xex);