Skip to content

Commit

Permalink
vmprofile: Extend Lua API and add test cases
Browse files Browse the repository at this point in the history
Extend the "Lua C API" for vmprofile to support allocating multiple
profiles and switching between them. This makes it easier to use.

Previously the expectation was that this functionality would be
implemented in Lua code using ljsyscall to allocate file-backed shared
memory for profiles and then the FFI to switch between them. (This is
still possible, too, and it works the same as it did before.)

Added test coverage to the test suite.
  • Loading branch information
lukego committed Jul 27, 2017
1 parent 65675f5 commit 8cd8f7e
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 9 deletions.
35 changes: 30 additions & 5 deletions src/lib_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,42 @@ LJLIB_CF(jit_opt_start)

#define LJLIB_MODULE_jit_vmprofile

LJLIB_CF(jit_vmprofile_open)
{
if (L->base < L->top && tvisstr(L->base)) {
return luaJIT_vmprofile_open(L, strdata(lj_lib_checkstr(L, 1)));
} else {
lj_err_argtype(L, 1, "filename");
return 0;
}
}

LJLIB_CF(jit_vmprofile_close)
{
if (L->base < L->top && tvislightud(L->base)) {
return luaJIT_vmprofile_close(L, lightudV(L->base));
} else {
lj_err_argtype(L, 1, "vmprofile");
}
}

LJLIB_CF(jit_vmprofile_select)
{
if (L->base < L->top && tvislightud(L->base)) {
return luaJIT_vmprofile_select(L, lightudV(L->base));
} else {
lj_err_argtype(L, 1, "vmprofile");
}
}

LJLIB_CF(jit_vmprofile_start)
{
luaJIT_vmprofile_start(L);
return 0;
return luaJIT_vmprofile_start(L);
}

LJLIB_CF(jit_vmprofile_stop)
{
luaJIT_vmprofile_stop(L);
return 0;
return luaJIT_vmprofile_stop(L);
}

#include "lj_libdef.h"
Expand All @@ -234,7 +260,6 @@ JIT_PARAMDEF(JIT_PARAMINIT)
0
};


/* Arch-dependent CPU detection. */
static uint32_t jit_cpudetect(lua_State *L)
{
Expand Down
44 changes: 42 additions & 2 deletions src/lj_vmprofile.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@
#define _GNU_SOURCE 1
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <signal.h>
#include <ucontext.h>
#undef _GNU_SOURCE

#include "lj_err.h"
#include "lj_obj.h"
#include "lj_dispatch.h"
#include "lj_jit.h"
Expand Down Expand Up @@ -99,15 +105,49 @@ static void stop_timer()

/* -- Lua API ------------------------------------------------------------- */

LUA_API void luaJIT_vmprofile_start(lua_State *L)
LUA_API int luaJIT_vmprofile_open(lua_State *L, const char *str)
{
int fd;
void *ptr;
if (((fd = open(str, O_RDWR|O_CREAT, 0666)) != -1) &&
((ftruncate(fd, sizeof(VMProfile))) != -1) &&
((ptr = mmap(NULL, sizeof(VMProfile), PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0)) != MAP_FAILED)) {
memset(ptr, 0, sizeof(VMProfile));
setlightudV(L->base, checklightudptr(L, ptr));
} else {
setnilV(L->base);
}
if (fd != -1) {
close(fd);
}
return 1;
}

LUA_API int luaJIT_vmprofile_close(lua_State *L, void *ud)
{
munmap(ud, sizeof(VMProfile));
return 0;
}

LUA_API int luaJIT_vmprofile_select(lua_State *L, void *ud)
{
setlightudV(L->base, checklightudptr(L, profile));
profile = (VMProfile *)ud;
return 1;
}

LUA_API int luaJIT_vmprofile_start(lua_State *L)
{
memset(&state, 0, sizeof(state));
state.g = G(L);
start_timer(1); /* Sample every 1ms */
return 0;
}

LUA_API void luaJIT_vmprofile_stop(lua_State *L)
LUA_API int luaJIT_vmprofile_stop(lua_State *L)
{
stop_timer();
return 0;
}

7 changes: 5 additions & 2 deletions src/luajit.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,11 @@ enum {
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);

/* VM profiling API. */
LUA_API void luaJIT_vmprofile_start(lua_State *L);
LUA_API void luaJIT_vmprofile_stop(lua_State *L);
LUA_API int luaJIT_vmprofile_start(lua_State *L);
LUA_API int luaJIT_vmprofile_open(lua_State *L, const char *str);
LUA_API int luaJIT_vmprofile_select(lua_State *L, void *ud);
LUA_API int luaJIT_vmprofile_close(lua_State *L, void *ud);
LUA_API int luaJIT_vmprofile_stop(lua_State *L);

/* Enforce (dynamic) linker error for version mismatches. Call from main. */
LUA_API void LUAJIT_VERSION_SYM(void);
Expand Down
1 change: 1 addition & 0 deletions testsuite/test/index
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ bc +luajit>=2
computations.lua
trace +jit
opt +jit
raptorjit
1 change: 1 addition & 0 deletions testsuite/test/raptorjit/index
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
vmprofile.lua
34 changes: 34 additions & 0 deletions testsuite/test/raptorjit/vmprofile.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
local vmprofile = require("jit.vmprofile")

do --- vmprofile start and stop
vmprofile.start()
vmprofile.stop()
end


do --- vmprofile multiple starts
for i = 1, 1000 do vmprofile.start() end
vmprofile.stop()
end

do --- vmprofile multiple profiles
vmprofile.start()
local a = vmprofile.open("a.vmprofile")
local b = vmprofile.open("b.vmprofile")
vmprofile.select(a)
for i = 1, 1e8 do end
vmprofile.select(b)
for i = 1, 1e8 do end
vmprofile.select(a)
for i = 1, 1e8 do end
vmprofile.stop()
vmprofile.close(a)
vmprofile.close(b)
-- simple sanity check that the profiles have different contents.
-- e.g. to make sure there was at least one sample taken somewhere.
assert(io.open("a.vmprofile", "r"):read("*a") ~=
io.open("b.vmprofile", "r"):read("*a"),
"check that profiles have different contents")
os.remove("a.vmprofile")
os.remove("b.vmprofile")
end

0 comments on commit 8cd8f7e

Please sign in to comment.