Skip to content

Commit 296fdfc

Browse files
committed
expose profiling api
1 parent d1e52e1 commit 296fdfc

3 files changed

Lines changed: 76 additions & 16 deletions

File tree

lib/sqlite3.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,24 @@ var isVerbose = false;
9393

9494
Database.prototype.addListener = Database.prototype.on = function(type) {
9595
var val = EventEmitter.prototype.addListener.apply(this, arguments);
96-
if (type === 'trace') {
97-
this.configure('trace', true);
96+
if (type === 'trace' || type === 'profile') {
97+
this.configure(type, true);
9898
}
9999
return val;
100100
};
101101

102102
Database.prototype.removeListener = function(type) {
103103
var val = EventEmitter.prototype.removeListener.apply(this, arguments);
104-
if (type === 'trace' && !this._events[type]) {
105-
this.configure('trace', false);
104+
if ((type === 'trace' || type === 'profile') && !this._events[type]) {
105+
this.configure(type, false);
106106
}
107107
return val;
108108
};
109109

110110
Database.prototype.removeAllListeners = function(type) {
111111
var val = EventEmitter.prototype.removeAllListeners.apply(this, arguments);
112-
if (type === 'trace') {
113-
this.configure('trace', false);
112+
if (type === 'trace' || type === 'profile') {
113+
this.configure(type, false);
114114
}
115115
return val;
116116
};

src/database.cc

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,7 @@ void Database::EIO_BeginClose(Baton* baton) {
209209
assert(baton->db->handle);
210210
assert(baton->db->pending == 0);
211211

212-
if (baton->db->debug_trace) {
213-
delete baton->db->debug_trace;
214-
baton->db->debug_trace = NULL;
215-
}
216-
212+
baton->db->RemoveCallbacks();
217213
eio_custom(EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
218214
}
219215

@@ -315,6 +311,11 @@ Handle<Value> Database::Configure(const Arguments& args) {
315311
Baton* baton = new Baton(db, handle);
316312
db->Schedule(RegisterTraceCallback, baton);
317313
}
314+
else if (args[0]->Equals(String::NewSymbol("profile"))) {
315+
Local<Function> handle;
316+
Baton* baton = new Baton(db, handle);
317+
db->Schedule(RegisterProfileCallback, baton);
318+
}
318319
else {
319320
return ThrowException(Exception::Error(String::Concat(
320321
args[0]->ToString(),
@@ -369,6 +370,49 @@ void Database::TraceCallback(EV_P_ ev_async *w, int revents) {
369370
queries.clear();
370371
}
371372

373+
void Database::RegisterProfileCallback(Baton* baton) {
374+
assert(baton->db->open);
375+
assert(baton->db->handle);
376+
Database* db = baton->db;
377+
378+
if (db->debug_profile == NULL) {
379+
// Add it.
380+
db->debug_profile = new AsyncProfile(db, ProfileCallback);
381+
sqlite3_profile(db->handle, ProfileCallback, db);
382+
}
383+
else {
384+
// Remove it.
385+
sqlite3_profile(db->handle, NULL, NULL);
386+
delete db->debug_profile;
387+
db->debug_profile = NULL;
388+
}
389+
390+
delete baton;
391+
}
392+
393+
void Database::ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs) {
394+
// Note: This function is called in the thread pool.
395+
// Note: Some queries, such as "EXPLAIN" queries, are not sent through this.
396+
static_cast<Database*>(db)->debug_profile->send(ProfileInfo(sql, nsecs));
397+
}
398+
399+
void Database::ProfileCallback(EV_P_ ev_async *w, int revents) {
400+
// Note: This function is called in the main V8 thread.
401+
HandleScope scope;
402+
AsyncProfile* async = static_cast<AsyncProfile*>(w->data);
403+
404+
std::vector<ProfileInfo> queries = async->get();
405+
for (unsigned int i = 0; i < queries.size(); i++) {
406+
Local<Value> argv[] = {
407+
String::NewSymbol("profile"),
408+
String::New(queries[i].first.c_str()),
409+
Integer::New((double)queries[i].second / 1000000.0)
410+
};
411+
EMIT_EVENT(async->parent->handle_, 3, argv);
412+
}
413+
queries.clear();
414+
}
415+
372416
Handle<Value> Database::Exec(const Arguments& args) {
373417
HandleScope scope;
374418
Database* db = ObjectWrap::Unwrap<Database>(args.This());
@@ -511,6 +555,17 @@ int Database::EIO_AfterLoadExtension(eio_req *req) {
511555
return 0;
512556
}
513557

558+
void Database::RemoveCallbacks() {
559+
if (debug_trace) {
560+
delete debug_trace;
561+
debug_trace = NULL;
562+
}
563+
if (debug_profile) {
564+
delete debug_profile;
565+
debug_profile = NULL;
566+
}
567+
}
568+
514569
/**
515570
* Override this so that we can properly close the database when this object
516571
* gets garbage collected.
@@ -537,10 +592,7 @@ void Database::Unref() {
537592
void Database::Destruct(Persistent<Value> value, void *data) {
538593
Database* db = static_cast<Database*>(data);
539594

540-
if (db->debug_trace) {
541-
delete db->debug_trace;
542-
db->debug_trace = NULL;
543-
}
595+
db->RemoveCallbacks();
544596

545597
if (db->handle) {
546598
eio_custom(EIO_Destruct, EIO_PRI_DEFAULT, EIO_AfterDestruct, db);

src/database.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ class Database : public EventEmitter {
133133
};
134134

135135
typedef Async<std::string, Database> AsyncTrace;
136+
typedef std::pair<std::string, sqlite3_uint64> ProfileInfo;
137+
typedef Async<ProfileInfo, Database> AsyncProfile;
136138

137139
friend class Statement;
138140

@@ -143,7 +145,8 @@ class Database : public EventEmitter {
143145
locked(false),
144146
pending(0),
145147
serialize(false),
146-
debug_trace(NULL) {
148+
debug_trace(NULL),
149+
debug_profile(NULL) {
147150

148151
}
149152

@@ -185,7 +188,11 @@ class Database : public EventEmitter {
185188
static void RegisterTraceCallback(Baton* baton);
186189
static void TraceCallback(void* db, const char* sql);
187190
static void TraceCallback(EV_P_ ev_async *w, int revents);
191+
static void RegisterProfileCallback(Baton* baton);
192+
static void ProfileCallback(void* db, const char* sql, sqlite3_uint64 nsecs);
193+
static void ProfileCallback(EV_P_ ev_async *w, int revents);
188194

195+
void RemoveCallbacks();
189196
void Wrap (Handle<Object> handle);
190197
inline void MakeWeak();
191198
virtual void Unref();
@@ -205,6 +212,7 @@ class Database : public EventEmitter {
205212
std::queue<Call*> queue;
206213

207214
AsyncTrace* debug_trace;
215+
AsyncProfile* debug_profile;
208216
};
209217

210218
}

0 commit comments

Comments
 (0)