The whole library

master
Pablo Musa 2014-03-13 09:53:54 -03:00
parent 3f0bc79436
commit 500ffcd661
67 changed files with 14293 additions and 3 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
# Todo file
todo.txt
# Object files
*.o
*.ko

BIN
FreeMono.ttf Normal file

Binary file not shown.

44
INSTALL Normal file
View File

@ -0,0 +1,44 @@
*
* Author: Pablo Musa
* Creation Date: jun 25 2011
* Last Modification: aug 22 2011
* See Copyright Notice in COPYRIGHT
*
* luamemprofiler - A Memory Profiler for the Lua language
*
INSTALL INSTRUCTIONS FOR LINUX:
luamemprofiler has three direct dependencies:
Lua 5.2
http://www.lua.org/work/
Download and Install (make, make install should do it).
SDL 1.2
http://www.libsdl.org/
Ubuntu:
sudo apt-get install libsdl1.2-dev libsdl1.2debian
SDL_ttf 2.0
http://www.libsdl.org/projects/SDL_ttf/
Ubuntu:
sudo apt-get install libsdl-ttf2.0-dev libsdl-ttf2.0-0
luamemprofiler also depends on FreeMono.ttf font.
Open the Makefile and edit the variables SDL_CFLAGS, SDL_LDFLAGS and LUA_DIR
changing the paths to fit your computer.
Then, open a console, go to the source folder containing the Makefile and type:
make
Then, type "lua5.2 tests/[test_name]" to execute the test.
The output is a memory usage report in the terminal.
Then, type "lua5.2 tests/$test_name $number" to execute the test with graphical
mode on. The report in the first execution should indicate what number you
should use.
Finally, copy the generated file (luamemprofiler.so) to the correct Lua lib
folder.
example: cp luamemprofiler.so /usr/local/lib/lua/5.2/

13
LICENSE
View File

@ -1,6 +1,15 @@
luamemprofiler License
---------------
luamemprofiler is licensed under the terms of the MIT license reproduced
below. This means that luamemprofiler is free software and can be used for both
academic and commercial purposes at absolutely no cost.
===============================================================================
The MIT License (MIT)
Copyright (c) 2014 Pablo Musa
Copyright (C) 2011 Pablo Musa, Roberto Ierusalimschy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -18,4 +27,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

45
Makefile Normal file
View File

@ -0,0 +1,45 @@
#
# Author: Pablo Musa
# Creation Date: mar 27 2011
# Last Modification: aug 22 2011
# See Copyright Notice in COPYRIGHT
#
# luamemprofiler - A Memory Profiler for the Lua language
#
SDL_CFLAGS = -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
SDL_LDFLAGS = -L/usr/lib -lSDL -lSDL_ttf
LUA_DIR = /home/pablomusa/aulas/2011.1/PFP/lua5.2/include
CC = gcc
# compilation should generate Dynamic-Link Libraries
CFLAGS = -g -Wall -O0 -ansi -pedantic
LFLAGS = -I$(LUA_DIR) -fpic -shared
all: luamemprofiler.so
luamemprofiler.so: graphic.o lmp_struct.o vmemory.o lmp.o luamemprofiler.o
$(CC) $(CFLAGS) $(LFLAGS) $(SDL_CFLAGS) $(SDL_LDFLAGS) graphic.o lmp_struct.o vmemory.o lmp.o luamemprofiler.o -o luamemprofiler.so
luamemprofiler.o: luamemprofiler.c lmp.h
$(CC) $(CFLAGS) $(LFLAGS) -c luamemprofiler.c
lmp.o: lmp.c lmp.h lmp_struct.h vmemory.h
$(CC) $(CFLAGS) -c lmp.c
lmp_struct.o: lmp_struct.c lmp_struct.h
$(CC) $(CFLAGS) -c lmp_struct.c
vmemory.o: vmemory.c lmp.h vmemory.h graphic.h
$(CC) $(CFLAGS) -c vmemory.c
graphic.o: gsdl.c graphic.h
$(CC) $(CFLAGS) $(SDL_CFLAGS) $(SDL_LDFLAGS) -c gsdl.c -o graphic.o
clean:
rm *.o
test:
./run.sh

View File

@ -1,4 +1,99 @@
luamemprofiler
==============
Lua Memory Profiler
A Memory Profiler for the Lua language
* Author: Pablo Musa
* Creation Date: jun 25 2011
* Last Modification: aug 22 2011
* See Copyright Notice in LICENSE
luamemprofiler is a library for the Lua language (version 5.2 or greater)
that collects information about the memory usage of a program throughout its
execution.
The memory profile of the program using our library can be shown graphically in
real time, detailing the different data types being allocated, reallocated or
released.
Our library also provides other useful information, such as the maximum amount
of memory allocated, the amount of each memory operation (malloc, free,
realloc) and the maximum number of each allocated object (function, string,
table, etc.).
Read INSTALL to see the library dependencies.
Use the following command to load the library into a local variable:
local lmp = require"luamemprofiler"
*
* luamemprofiler API
*
-- starts the memory monitor.
-- if the optional parameter is used, the library starts the graphical display
-- and enables different inspection features.
-- optional parameter must be a number.
lmp.start([estimated_memory_use_in_MB])
-- stops the memory monitor.
-- prints a log on the standard output.
-- if the graphical display was used it is then destroyed.
lmp.stop()
*
* luamemprofiler graphical display functionalities
*
During library execution WITH GRAPHICAL DISPLAY, there are two main states
of the luamemprofiler library: PAUSED and EXECUTING.
EXECUTING:
one can see the blocks painted in the screen representing each memory
operation. The following option is enabled:
space - stops program execution and changes the library state to PAUSED.
PAUSED:
one can use keyboard and mouse events to explore memory usage. The following
options are enabled:
space - changes the library state to EXECUTING and resume execution.
n - program executes until next memory operation. The library prints in the
window bottom: the memory operation (malloc, free or realloc), the block
address, the block type (table, string, etc.), the block size and the call
stack (3 levels most).
c - clear the memory box. Note this key must be pressed before one can start
filtering blocks by type. Otherwise the other commands just overdraw blocks.
a - toggle all types and redraw all blocks.
s - String: toggle/untoggle type and draw/erase type blocks.
f - Function: toggle/untoggle type and draw/erase type blocks.
u - Userdata: toggle/untoggle type and draw/erase type blocks.
h - Thread: toggle/untoggle type and draw/erase type blocks.
t - Table: toggle/untoggle type and draw/erase type blocks.
o - Other: toggle/untoggle type and draw/erase type blocks. (these blocks are
internal structures that are not well typed by Lua. For example, table contents
have this type).
Mouse1 - Zoom IN. All blocks that follows 'y' coordinate clicked are redrawn
with bigger size and new baseaddress. One can then opt to use all the keys
enabled (PAUSED and EXECUTING mode).
Mouse2 - Zoom OUT. All blocks are redrawn using the default size and the
default baseaddress.
*
* Some Considerations
*
Calling the start function twice raises an error.
The start can be used in any part of the program, so can the stop function if
it comes after a start call.
The library monitors only the interval between start and stop. Memory operations
done before the start call, or after the stop call are not counted.
Blocks that the address do not fit in the memory box are not painted.

52
calc_screen.lua Normal file
View File

@ -0,0 +1,52 @@
local bytes_per_pixel = {4, 8, 12, 16, 32}
function num_of_pixels(w, h)
return w * (h/2)
end
function num_of_bytes(nop, bpp)
return bpp * nop
end
function resolution(bpp, memused)
local side = math.sqrt(memused * 1000000 * 2 / bpp / (4*3))+ 1;
local w = side * 4;
local h = side * 3;
return w, h
end
local op = 1
while op do
print("Digite 1 para numero de bytes, 2 para resolução, 3 para bytes per pixel")
op = tonumber(io.read())
if op == 1 then
print("Entre com a largura:")
local w = tonumber(io.read())
print("Entre com a altura:")
local h = tonumber(io.read())
for v=4,32,4 do
local nop = num_of_pixels(w,h)
local nob = num_of_bytes(nop, v)
print(string.format("%d bytes %d x %d | %d | %d", v, w, h, nop, nob))
end
elseif op == 2 then
print("Entre com a memoria maxima usada:")
local mmu = tonumber(io.read())
for v=4,32,4 do
local w, h = resolution(v, mmu)
print(string.format("%d bytes %d x %d", v, w, h))
end
elseif op == 3 then
print("Entre com a memoria maxima usada:")
local mmu = tonumber(io.read())
local nop = num_of_pixels(800, 600)
print(string.format("%d bytes %d x %d", mmu*1000000/nop, 800, 600))
else
op = nil
end
end

1
gdb.sh Executable file
View File

@ -0,0 +1 @@
LD_PRELOAD=/lib/libpthread.so.0 gdb --args lua5.2 $@

145
graphic.h Normal file
View File

@ -0,0 +1,145 @@
/*
**
** Author: Pablo Musa
** Creation Date: mar 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** This is the header file of the drawing module. There is no graphic tool
** attached to our implementation. One can choose any graphic library to
** implement the graphic module. But one must implement all functions of
** this file and respect their contracts.
** If you are going to implement the graphic module using another graphic
** tool, please pay attention to the functions definitions.
**
*/
#ifndef LMP_GRAPHIC_H
#define LMP_GRAPHIC_H
#define LMP_EVENT_EMPTY 0
#define LMP_EVENT_KEY 1
#define LMP_EVENT_MOUSE 2
#define LEFT_BUTTON 1
#define RIGHT_BUTTON 3
#define FONT_SIZE 16
#define mkColor(r,g,b) ((r) | ((g) << 8) | ((b) << 16))
#define getRed(c) ((c) & 0xFF)
#define getGreen(c) (((c) & 0xFF00) >> 8)
#define getBlue(c) (((c) & 0xFF0000) >> 16)
#define DARKBLUE mkColor(0, 0, 139)
#define DARKRED mkColor(139, 0, 0)
#define DARKGREEN mkColor(0, 100, 0)
#define DARKORANGE mkColor(255, 140, 0)
#define DARKMAGENTA mkColor(139, 0, 139)
#define DIMGRAY mkColor(105, 105, 105)
#define LTWHITE mkColor(240, 240, 240)
#define LTGRAY mkColor(211, 211, 211)
#define WHITE mkColor(255, 255, 255)
#define BLACK mkColor(0, 0, 0)
#define RED mkColor(255, 0, 0)
struct kevent {
int key;
};
struct mevent {
int x, y, b;
};
union LMP_event {
struct kevent kevent;
struct mevent mevent;
};
typedef union LMP_event LMP_Event;
/*
** There are some available colors predefined in the beginning of this file.
** Use the macros: get(Red, Green, Blue) to map from Color to R, G or B.
*/
typedef long Color;
typedef void Screen;
typedef void Font;
/*
** Create a new window with the specified width, height, icon and title.
** This function must load a base font if the graphic tool does not have
** one by default. This font will be used by other functions.
** Returns the screen pointer.
*/
Screen *gr_newscreen (int width,int height,const char *icon,const char *title);
/*
** Destroy the window referenced by the screen pointer.
** This function must unload the font if any font was loaded in gr_newscreen.
*/
void gr_destroyscreen (Screen *screen);
/*
** Draw a line in the window from (x0,y0) to (x1, y1).
*/
void gr_drawline (Screen *screen, int x0 , int y0 , int x1, int y1 );
/*
** Draw an horizontal block from (x0,y) to x1 with blockheight.
*/
void gr_drawblock (Screen *screen, int x0 , int x1 , int y, int blockheight);
/*
** Write the specified text beginning at (x,y).
*/
void gr_drawtext (Screen *screen, const char *text, int x, int y);
/*
** Paint all window with the specified color.
** See Color typedef (beginning of this file) for more details about Color.
*/
void gr_drawbackground (Screen *screen, Color color);
/*
** Set the specified color for any following draw.
** See Color typedef (beginning of this file) for more details about Color.
*/
void gr_setdrawcolor(Screen *screen, Color color);
/*
** Set the specified color for any following text.
** See Color typedef (beginning of this file) for more details about Color.
*/
void gr_settextcolor (Screen *screen, Color color);
/*
** Return the width of one text character in pixels.
*/
int gr_gettextwidth(Screen *screen);
/*
** Return the height of one text character in pixels.
*/
int gr_gettextheight(Screen *screen);
/*
** Search for a keyboard or mouse event until queue is empty.
** Return an int containing the event type (mouse, keyboard or empty).
** This function removes all events from the top of the queue that are not
** keydown or mousebuttondown events.
*/
int gr_getevent(Screen *screen, LMP_Event *event);
/*
** Wait until a keyboard or mouse event occur.
** Returns an int containing the event type (mouse, keyboard or empty).
** This function discards all events from the top of the queue that are not
** keydown or mousebuttondown events.
*/
int gr_waitevent(Screen *screen, LMP_Event *event);
#endif

214
gsdl.c Normal file
View File

@ -0,0 +1,214 @@
/*
**
** Author: Pablo Musa
** Creation Date: mar 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** This file contains the implementation of the graphic module (graphic.h)
** using the SDL graphic toolkit and the SDL_ttf library.
** See graphic.h for more details about the functions
*/
#include <SDL.h>
#include <SDL_ttf.h>
#include "graphic.h"
/* GLOBAL VARIABLES */
static TTF_Font *font;
static SDL_Colour fontcolor = {0,0,0};
static Uint32 color;
static int gr_textwidth;
static int gr_textheight;
/* STATIC FUNCTIONS */
static TTF_Font* loadfont(char* file, int ptsize);
/* GLOBAL FUNCTIONS */
Screen *gr_newscreen(int width,int height,const char *icon,const char *title) {
int depth = 32;
SDL_Surface *screen;
Uint32 vmode = SDL_HWSURFACE | SDL_ANYFORMAT | SDL_RESIZABLE |
SDL_DOUBLEBUF | SDL_HWPALETTE;
if (SDL_Init(SDL_INIT_VIDEO) == -1)
return NULL;
SDL_WM_SetIcon(SDL_LoadBMP(icon), NULL);
screen = SDL_SetVideoMode(width, height, depth, vmode);
if(!screen){
printf("Unable to set video mode: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_WM_SetCaption(title, 0);
if (TTF_Init() == -1) {
printf("Unable to initialize SDL_ttf(fonts): %s \n", TTF_GetError());
exit(EXIT_FAILURE);
}
font = loadfont("FreeMono.ttf", FONT_SIZE);
return (Screen*) screen;
}
void gr_destroyscreen (Screen *screen) {
TTF_Quit();
SDL_Quit();
}
/* DRAW FUNCTIONS */
/* Bresenham's line_algorithm */
void gr_drawline (Screen *screen, int x0, int y0, int x1, int y1) {
int pos, dx, dy, sx, sy, err;
SDL_Surface *sdl_screen = (SDL_Surface*) screen;
dx = abs(x1 - x0);
dy = abs(y1 - y0);
if (x0 < x1) sx = 1; else sx = -1;
if (y0 < y1) sy = 1; else sy = -1;
err = dx-dy;
while(x0 != x1 || y0 != y1) {
int pos = (sdl_screen->w * y0) + x0;
int e2 = err + err;
((Uint32 *) sdl_screen->pixels)[pos] = color;
if (e2 > -dy) {
err = err - dy;
x0 = x0 + sx;
}
if (e2 < dx) {
err = err + dx;
y0 = y0 + sy;
}
}
/* draw last pixel */
pos = (sdl_screen->w * y0) + x0;
((Uint32 *) sdl_screen->pixels)[pos] = color;
SDL_Flip(sdl_screen);
}
void gr_drawblock (Screen *screen, int x0 , int x1 , int y, int blockheight) {
SDL_Surface *sdl_screen = (SDL_Surface*) screen;
int i, pos = (sdl_screen->w * y) + x0;
int dx = x1 - x0 + 1; /* +1 -> draw x0 AND x1 */
int y1 = y + blockheight; /* draw y but not y1 */
while(y < y1) {
for (i = x0; i <= x1; i++, pos++) {
((Uint32 *) sdl_screen->pixels)[pos] = color;
}
pos = pos + sdl_screen->w - dx; /* go to the beginning of the next line */
y++;
}
SDL_Flip(screen);
}
void gr_drawtext(Screen *screen, const char *text, int x, int y) {
SDL_Surface *tsurface = TTF_RenderText_Solid(font, text, fontcolor);
SDL_Rect rect;
rect.x = x;
rect.y = y;
if(!tsurface) {
printf("Unable to write text: %s \n", TTF_GetError());
exit(EXIT_FAILURE);
} else {
SDL_BlitSurface(tsurface, NULL, screen, &rect);
SDL_Flip(screen);
SDL_FreeSurface(tsurface);
}
}
void gr_drawbackground(Screen *screen, Color clr) {
SDL_Surface *sdl_screen = (SDL_Surface*) screen;
color = SDL_MapRGB(sdl_screen->format, getRed(clr), getGreen(clr),
getBlue(clr));
SDL_FillRect(sdl_screen, &sdl_screen->clip_rect, color);
SDL_Flip(sdl_screen);
}
/* SET FUNCTIONS */
void gr_setdrawcolor(Screen *screen, Color clr) {
SDL_Surface *sdl_screen = (SDL_Surface*) screen;
color = SDL_MapRGB(sdl_screen->format, getRed(clr), getGreen(clr),
getBlue(clr));
}
void gr_settextcolor (Screen *screen, Color clr) {
fontcolor.r = getRed(clr);
fontcolor.g = getGreen(clr);
fontcolor.b = getBlue(clr);
}
/* GET FUNCTIONS */
int gr_gettextwidth(Screen *screen) {
return gr_textwidth;
}
int gr_gettextheight(Screen *screen) {
return gr_textheight;
}
/* EVENT FUNCTIONS */
int gr_getevent(Screen *screen, LMP_Event *event) {
int res;
SDL_Event sdlevent;
/* search for a keyboard or mouse event until list is empty */
res = SDL_PollEvent(&sdlevent);
while (res == 1) {
if (sdlevent.type == SDL_KEYDOWN) {
event->kevent.key = sdlevent.key.keysym.sym;
return LMP_EVENT_KEY;
} else if (sdlevent.type == SDL_MOUSEBUTTONDOWN) {
event->mevent.x = sdlevent.button.x;
event->mevent.y = sdlevent.button.y;
return LMP_EVENT_MOUSE;
}
res = SDL_PollEvent(&sdlevent);
}
/* no more events in the list */
return LMP_EVENT_EMPTY;
}
int gr_waitevent(Screen *screen, LMP_Event *event) {
int res;
SDL_Event sdlevent;
/* wait until a keyboard or mouse event occur. discard other events */
res = SDL_WaitEvent(&sdlevent);
while (res == 1) {
if (sdlevent.type == SDL_KEYDOWN) {
event->kevent.key = sdlevent.key.keysym.sym;
return LMP_EVENT_KEY;
} else if (sdlevent.type == SDL_MOUSEBUTTONDOWN) {
event->mevent.b = sdlevent.button.button; /* 1 - Left | 3 - Right */
event->mevent.x = sdlevent.button.x;
event->mevent.y = sdlevent.button.y;
return LMP_EVENT_MOUSE;
}
res = SDL_WaitEvent(&sdlevent);
}
printf("Unable to wait for an event!\n");
exit(EXIT_FAILURE);
}
/* STATIC FUNCTIONS */
static TTF_Font* loadfont(char* file, int ptsize) {
TTF_Font *tmpfont = TTF_OpenFont(file, ptsize);
if (tmpfont == NULL){
printf("Unable to load font: %s %s \n", file, TTF_GetError());
exit(EXIT_FAILURE);
}
TTF_SizeText(tmpfont, "0", &gr_textwidth, &gr_textheight);
return tmpfont;
}

228
lmp.c Normal file
View File

@ -0,0 +1,228 @@
/*
**
** Author: Pablo Musa
** Creation Date: may 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** See lmp.h for module overview
**
*/
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "lmp.h"
#include "vmemory.h"
#include "lmp_struct.h"
#define LMP_FREE 0
#define LMP_MALLOC 1
#define LMP_REALLOC 2
/* STATIC VARIABLES */
/* ac = allocation counter */
static int ac_string, ac_function, ac_userdata, ac_thread, ac_table, ac_other;
static long nallocs, alloc_size;
static long nreallocs, realloc_size;
static long nfrees, free_size;
static long memoryuse, maxmemoryuse;
static int Laddress;
static int Maddress = 0;
static int usegraphics;
/* STATIC FUNCTIONS */
static void *lmp_malloc(size_t nsize, size_t osize);
static void *lmp_free(void *ptr);
static void *lmp_realloc(void *ptr, size_t nsize);
static void initcounters();
static void updatecounters(int alloctype, size_t size, size_t luatype);
static void generatereport();
/* PUBLIC FUNCTIONS */
void lmp_start(int lowestaddress, float memused, int usegraphic) {
initcounters();
st_newhash(usegraphic);
usegraphics = usegraphic;
Laddress = lowestaddress; /* save lowest address to calc mem needed */
if (usegraphics)
vm_start(lowestaddress, memused);
}
void lmp_stop() {
generatereport();
/* erase counters and blocks */
initcounters();
st_destroyhash();
if (usegraphics)
vm_stop();
}
/* allocation function used by Lua when luamemprofiler is used */
void *lmp_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void) ud;
(void) osize;
if (nsize == 0) { /* calls our malloc, free or realloc functions */
return lmp_free(ptr);
} else if (ptr == NULL) {
return lmp_malloc(nsize, osize); /* osize is the lua_type */
} else {
return lmp_realloc(ptr, nsize);
}
}
/* STATIC FUNCTIONS */
/* does normal malloc and then alloc and update other structures */
static void *lmp_malloc(size_t nsize, size_t luatype) {
void *ptr = malloc(nsize); /* normal malloc */
lmp_Block *new = (lmp_Block *) malloc (sizeof(lmp_Block));
st_initblock(new, ptr, nsize, luatype);
st_insertblock(new);
updatecounters(LMP_MALLOC, nsize, luatype);
if ((int) ptr > Maddress) /* save max address to calc mem needed */
Maddress = (int) ptr;
if (usegraphics) /* if graphics enabled call function to handle */
vm_newmemop(LMP_VM_MALLOC, ptr, luatype, nsize);
return ptr;
}
/* free and update other structures and then does normal free */
static void *lmp_free(void *ptr) {
lmp_Block *block = st_removeblock(ptr);
if (block != NULL) {
int size = st_getsize(block);
updatecounters(LMP_FREE, size, 0);
if (usegraphics) { /* if graphics enabled call function to handle */
vm_newmemop(LMP_VM_FREE, ptr, LUA_TFREE, size);
}
free(block);
}
free(ptr);
return NULL;
}
/*
** does normal realloc, assumes realloc always change object address (wich is
** not true, but is simplier to program and costless) and updates block
** information. then, if usegraphics, verify if realloc is enlarging or
** shrinking and call vm_newop with the correct values. Optimise drawing if
** realloc uses same object address. Finally, update counters.
*/
static void *lmp_realloc(void *ptr, size_t nsize) {
lmp_Block *block;
size_t osize;
void *p = realloc(ptr, nsize);
if (p == NULL) return NULL;
block = st_removeblock(ptr); /* realloc usually changes memory address */
if (block != NULL) {
osize = st_getsize(block);
st_setsize(block, nsize);
st_setptr(block, p);
st_insertblock(block);
if (usegraphics) {
int luatype = st_getluatype(block);
if (ptr != p) { /* memory location changed */
vm_newmemop(LMP_VM_REALLOC, ptr, LUA_TFREE, osize); /*erase old block*/
vm_newmemop(LMP_VM_REALLOC, p, luatype, nsize);
} else {
if (nsize > osize) { /* enlarging block */
vm_newmemop(LMP_VM_REALLOC, (char *) ptr + osize, luatype, nsize - osize);
} else if (osize > nsize) { /* shrinking block - erase extra part */
vm_newmemop(LMP_VM_REALLOC, (char*) ptr + nsize, LUA_TFREE, osize - nsize);
}
}
}
updatecounters(LMP_REALLOC, nsize - osize, 0);
}
return p;
}
/* STATIC FUNCTIONS */
static void initcounters() {
ac_string=0;ac_function=0;ac_userdata=0;ac_thread=0;ac_table=0;ac_other=0;
nallocs=0;alloc_size=0;
nreallocs=0;realloc_size=0;
nfrees=0;free_size=0;
memoryuse=0;maxmemoryuse=0;
}
/* check alloctype and update counters accordingly */
static void updatecounters (int alloctype, size_t size, size_t luatype) {
if (alloctype == LMP_FREE) {
nfrees = nfrees + 1;
free_size = free_size + size;
memoryuse = memoryuse - size;
} else if (alloctype == LMP_REALLOC) {
nreallocs = nreallocs + 1;
realloc_size = realloc_size + size;
memoryuse = memoryuse + size;
if (memoryuse > maxmemoryuse) {
maxmemoryuse = memoryuse;
}
} else if (alloctype == LMP_MALLOC) {
nallocs = nallocs + 1;
alloc_size = alloc_size + size;
memoryuse = memoryuse + size;
if (memoryuse > maxmemoryuse) {
maxmemoryuse = memoryuse;
}
switch(luatype) {
case LUA_TSTRING:
ac_string++;
break;
case LUA_TFUNCTION:
ac_function++;
break;
case LUA_TUSERDATA:
ac_userdata++;
break;
case LUA_TTHREAD:
ac_thread++;
break;
case LUA_TTABLE:
ac_table++;
break;
default:
ac_other++;
}
}
}
/*
** writes the report in the standard output. If not usegraphics, calculates
** program memory usage and sugest memory consumption parameter for future
** execution.
*/
static void generatereport() {
float mem = ((float) (Maddress - Laddress) / 1000000) + 0.1;
if (!usegraphics)
mem = mem + 0.4; /* empiric size of graphic mem usage */
printf("===================================================================\n");
printf("Number of Mallocs=%ld\tTotal Malloc Size=%ld\n", nallocs, alloc_size);
printf("Number of Reallocs=%ld\tTotal Realloc Size=%ld\n", nreallocs, realloc_size);
printf("Number of Frees=%ld\tTotal Free Size=%ld\n", nfrees, free_size);
printf("\nNumber of Allocs of Each Type:\n");
printf(" String=%d | Function=%d | Usedata=%d | Thread=%d | Table=%d | Other=%d\n", ac_string, ac_function, ac_userdata, ac_thread, ac_table, ac_other);
printf("\nMaximum Memory Used=%ld bytes\n", maxmemoryuse);
if (!usegraphics && nallocs > 0) {
printf("\nWe suggest you run the application again using %.1f as parameter\n", mem);
}
printf("===================================================================\n");
}

39
lmp.h Normal file
View File

@ -0,0 +1,39 @@
/*
**
** Author: Pablo Musa
** Creation Date: may 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** This module is responsible by defining the new allocation function and
** by collecting all information about memory management.
** At the end of the program execution or when luamemprofiler.stop() is
** called, it generates a log containing several memory information.
**
*/
#ifndef LMP_LMP_H
#define LMP_LMP_H
/*
** Initializes the counters, sets the lowest address of the heap and
** enables/disables the use of the graphic module (vm_start).
*/
void lmp_start (int lowestaddress, float memused, int usegraphics);
/*
** Finalizes the counters, free all blocks structures, stop the graphic
** module (vm_stop) [if started] and generates the report (number of: mallocs,
** frees, tables, ...).
*/
void lmp_stop ();
/*
** Checks the alloc type (malloc, free, realloc) and update data in
** accordance. Create, remove or update block structures, update report
** counters (mallocs, tables, etc.) and call vm_newmemop if graphic
** module is enabled.
*/
void *lmp_alloc (void *ud, void *ptr, size_t osize, size_t nsize);
#endif

206
lmp_struct.c Normal file
View File

@ -0,0 +1,206 @@
/*
**
** Author: Pablo Musa
** Creation Date: aug 16 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** See lmp_struct.h for module overview
**
*/
#include "lmp_struct.h"
#include "lua.h"
#define HASH_SIZE 23 /* empiric hash size - need more tests to confirm */
/* simple hash function */
static int hashfunc(void *ptr) {
return ((unsigned int) ptr) % HASH_SIZE;
}
/* STATIC GLOBAL VARIABLE */
static lmp_Block **lmp_head = NULL; /* hashtable for all blocks */
static int usegraphics;
/* GLOBAL VARIABLES - filter lists */
/* multiply linked lists used for type filtering. used only in graphic mode */
lmp_Block *lmp_string = NULL;
lmp_Block *lmp_function = NULL;
lmp_Block *lmp_userdata = NULL;
lmp_Block *lmp_thread = NULL;
lmp_Block *lmp_table = NULL;
lmp_Block *lmp_other = NULL;
lmp_Block *lmp_all = NULL; /* used to redraw all blocks */
void st_newhash(int usegraphic) {
int i;
usegraphics = usegraphic;
lmp_head = (lmp_Block **) malloc (HASH_SIZE * sizeof(lmp_Block*));
for (i = 0; i < HASH_SIZE; i++) {
lmp_head[i] = NULL;
}
}
void st_destroyhash() {
int i;
for(i = 0; i < HASH_SIZE; i++) {
lmp_Block *p;
lmp_Block *head = lmp_head[i];
while (head != NULL) {
p = head;
head = head->next;
free(p);
}
}
free(lmp_head);
if (usegraphics) {
lmp_string = NULL;
lmp_function = NULL;
lmp_userdata = NULL;
lmp_thread = NULL;
lmp_table = NULL;
lmp_other = NULL;
lmp_all = NULL;
}
}
lmp_Block *st_removeblock (void *ptr) {
lmp_Block *p, *ant = NULL;
int i = hashfunc(ptr);
for (p = lmp_head[i]; p != NULL; ant = p, p = p->next) {
if (p->ptr == ptr) {
if (ant == NULL) {
lmp_head[i] = p->next;
} else {
ant->next = p->next;
}
p->next = NULL;
if (usegraphics) {
if (p->prevtype != NULL) {
p->prevtype->nexttype = p->nexttype;
}
if (p->nexttype != NULL) {
p->nexttype->prevtype = p->prevtype;
}
if (p->prevall != NULL) {
p->prevall->nextall = p->nextall;
}
if (p->nextall != NULL) {
p->nextall->prevall = p->prevall;
}
}
return p;
}
}
return NULL;
}
void st_insertblock (lmp_Block *block) {
lmp_Block **type;
int i = hashfunc(block->ptr);
block->next = lmp_head[i];
lmp_head[i] = block;
if (usegraphics) {
switch (block->luatype) {
case LUA_TSTRING:
type = &lmp_string;
break;
case LUA_TFUNCTION:
type = &lmp_function;
break;
case LUA_TUSERDATA:
type = &lmp_userdata;
break;
case LUA_TTHREAD:
type = &lmp_thread;
break;
case LUA_TTABLE:
type = &lmp_table;
break;
default: /* OTHER */
type = &lmp_other;
break;
}
if (*type != NULL) {
(*type)->prevtype = block;
}
block->nexttype = *type;
block->prevtype = NULL;
*type = block;
if (lmp_all != NULL) {
lmp_all->prevall = block;
}
block->nextall = lmp_all;
block->prevall = NULL;
lmp_all = block;
}
}
void st_initblock (lmp_Block *block, void *ptr, size_t size, size_t luatype) {
block->ptr = ptr;
block->size = size;
block->luatype = luatype;
block->next = NULL;
if (usegraphics) {
block->nexttype = NULL;
block->prevtype = NULL;
block->nextall = NULL;
block->prevall = NULL;
}
}
void *st_getptr(lmp_Block *block) {
return block->ptr;
}
size_t st_getsize(lmp_Block *block) {
return block->size;
}
size_t st_getluatype(lmp_Block *block) {
return block->luatype;
}
lmp_Block *st_getnext(lmp_Block *block) {
return block->next;
}
lmp_Block *st_getnexttype(lmp_Block *block) {
return usegraphics ? block->nexttype : NULL;
}
lmp_Block *st_getprevtype(lmp_Block *block) {
return usegraphics ? block->prevtype : NULL;
}
lmp_Block *st_getnextall(lmp_Block *block) {
return usegraphics ? block->nextall : NULL;
}
lmp_Block *st_getprevall(lmp_Block *block) {
return usegraphics ? block->prevall : NULL;
}
void st_setsize(lmp_Block *block, size_t size) {
block->size = size;
}
void st_setptr(lmp_Block *block, void *ptr) {
block->ptr = ptr;
}

89
lmp_struct.h Normal file
View File

@ -0,0 +1,89 @@
/*
**
** Author: Pablo Musa
** Creation Date: aug 16 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** This module is responsible by defining the block structure used keep
** information of each allocation and by implementing data structures to
** hold these blocks. The main data structure is a hash table with predefined
** size and separate chaining with list heads. There are other seven multiply
** linked lists used for type filtering. However these lists are used just in
** the graphic module and do not produce overhead when graphics are disabled.
**
*/
#ifndef LMP_LMPSTRUCT_H
#define LMP_LMPSTRUCT_H
#include <stdlib.h>
/*
** Holds memory address, size and type of each block allocated.
** Can have connection with 3 structures (hash table, type list and all list).
** The hash table is the module main structure, the 'type list' is the list
** where all blocks of a specific types are linked. The 'all list' is a list
** where all blocks are sequentially linked.
*/
struct lmp_block {
void *ptr;
size_t size;
size_t luatype;
struct lmp_block *next;
struct lmp_block *nexttype;
struct lmp_block *prevtype;
struct lmp_block *nextall;
struct lmp_block *prevall;
};
typedef struct lmp_block lmp_Block;
/*
** Sets global usegraphics, malloc and initialize the hash table.
*/
void st_newhash(int usegraphic);
/*
** Destroy and free the hash table and if usegraphics reset filter lists.
*/
void st_destroyhash();
/*
** Searches for a block with specified ptr address. If the block is found,
** removes the block from the hash table. If usegraghics, also removes
** the block from his specific 'filter list' and from 'all list'.
*/
lmp_Block *st_removeblock (void *ptr);
/*
** Inserts the specified block into the hash table. If usegraphics, also
** inserts the block into his specific 'filter list' and into 'all list'.
*/
void st_insertblock (lmp_Block *block);
/*
** Initializes the specified block with the specified values and sets the
** hash table pointer to NULL. If usegraphics, initialize the other pointers.
*/
void st_initblock (lmp_Block *block, void *ptr, size_t nsize, size_t luatype);
/*
** Gets and Sets.
*/
void *st_getptr(lmp_Block *block);
size_t st_getsize(lmp_Block *block);
size_t st_getluatype(lmp_Block *block);
lmp_Block *st_getnext(lmp_Block *block);
lmp_Block *st_getnexttype(lmp_Block *block);
lmp_Block *st_getprevtype(lmp_Block *block);
lmp_Block *st_getnextall(lmp_Block *block);
lmp_Block *st_getprevall(lmp_Block *block);
void st_setsize(lmp_Block *block, size_t size);
void st_setptr(lmp_Block *block, void *ptr);
#endif

BIN
logo.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

150
luamemprofiler.c Normal file
View File

@ -0,0 +1,150 @@
/*
** Author: Pablo Musa
** Creation Date: mar 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** This module is responsible for registering the luamemprofiler lib in the
** Lua environment. It also sets a finalizer for the luamemprofiler library
** which restores the lua_State original function when the library is garbage
** collected.
** The library implements two main functions (start and stop).
** The start function receives an optional parameter (a number containing
** the expected memory consumption) which determines if the library will
** display real-time information and the granularity of the blocks.
**
*/
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "lmp.h"
/* Keeps the default allocation function and the ud of a lua_State */
typedef struct lmp_allocstructure {
lua_Alloc f;
void *ud;
} lmp_Alloc;
/*
** Called when main program ends.
** Restores lua_State original allocation function.
*/
static int finalize (lua_State *L) {
lmp_Alloc *s;
/* check lmp_Alloc */
if (!lua_isuserdata(L, -1)) {
lua_pushstring(L, "incorrect argument");
lua_error(L);
}
/* get lmp_Alloc and restore original allocation function */
s = (lmp_Alloc *) lua_touserdata(L, -1);
if (s->f != lua_getallocf (L, NULL)) {
lua_setallocf(L, s->f, s->ud);
lmp_stop();
}
return 0;
}
/* Register finalize function as metatable */
static void create_finalizer(lua_State *L, lua_Alloc f, void *ud) {
lmp_Alloc *s;
/* create metatable with finalize function (__gc field) */
luaL_newmetatable(L, "luamemprofiler_mt");
lua_pushcfunction(L, finalize);
lua_setfield(L, -2, "__gc");
/* create 'alloc' userdata (one ud for each Lua_State) */
s = (lmp_Alloc*) lua_newuserdata(L, (size_t) sizeof(lmp_Alloc));
s->f = f;
s->ud = ud;
/* set userdata metatable */
luaL_setmetatable(L, "luamemprofiler_mt");
/* insert userdata into registry table so it cannot be collected */
lua_setfield(L, LUA_REGISTRYINDEX, "luamemprofiler_ud");
}
/* Main module function. Starts the library */
static int luamemprofiler_start(lua_State *L) {
static lua_Alloc f;
static void *ud;
float memused;
int usegraphics = 0;
/* get the amount of memory expected to be used AND set enable graphics */
memused = (float) lua_tonumber(L, 1);
if (memused)
usegraphics = 1;
/* get default allocation function */
f = lua_getallocf(L, &ud);
/* check if start has been called before */
if (f == lmp_alloc) {
/* restore default allocation function and remove library finalizer */
lmp_Alloc *s;
lua_getfield(L, LUA_REGISTRYINDEX, "luamemprofiler_ud");
s = (lmp_Alloc *) lua_touserdata(L, -1);
lua_setallocf(L, s->f, s->ud);
lua_getmetatable(L, -1);
lua_pushnil(L);
lua_setfield(L, -2, "__gc");
lua_pushstring(L, "calling luamemprofiler start function twice");
lua_error(L);
}
/* create data_structure and set finalizer */
create_finalizer(L, f, ud);
lua_setallocf(L, lmp_alloc, ud);
/* L is in most cases the lowest address of the heap (easiest to access) */
lmp_start((int) L, memused, usegraphics);
return 0;
}
/* restore default allocation function and stop the other modules */
static int luamemprofiler_stop(lua_State *L) {
lmp_Alloc *s;
/* get 'alloc' userdata and restore original allocation function */
lua_pushstring(L, "luamemprofiler_ud");
lua_rawget(L, LUA_REGISTRYINDEX);
s = (lmp_Alloc*) lua_touserdata(L, -1);
if (s == NULL) {
lua_pushstring(L, "calling luamemprofiler stop function without calling start function");
lua_error(L);
}
lua_pop(L, 1);
lua_setallocf(L, s->f, s->ud);
lmp_stop();
return 0;
}
/**********************************
* register structs and functions *
**********************************/
/* luamemprofiler function registration array */
static const luaL_Reg luamemprofiler[] = {
{ "start", luamemprofiler_start},
{ "stop", luamemprofiler_stop},
{ NULL, NULL }
};
/* register luamemprofiler functions */
LUALIB_API int luaopen_luamemprofiler (lua_State *L) {
luaL_newlib(L, luamemprofiler);
return 1;
}

21
run.sh Executable file
View File

@ -0,0 +1,21 @@
#############################################################################
# Author: Pablo Musa #
# Creation Date: mar 27 2011 #
# Last Modification: aug 09 2011 #
# #
# Script for automated test #
#############################################################################
TESTS=tests
OUT=$TESTS/out
for i in $TESTS/*.lua
do
i=`basename $i .lua`
# echo "lua5.2 $TESTS/$i.lua > tmp.txt"
lua5.2 $TESTS/$i.lua > tmp.txt
echo "diff tmp.txt $OUT/$i.txt"
diff $OUT/$i.txt tmp.txt
done
rm tmp.txt

495
tests/.svn/entries Normal file
View File

@ -0,0 +1,495 @@
10
dir
2
http://subversion.assembla.com/svn/luamemprofiler/trunk/tests
http://subversion.assembla.com/svn/luamemprofiler
2011-03-27T15:30:06.151736Z
2
pablomusa
svn:special svn:externals svn:needs-lock
2addb8f8-2ff2-4263-acf2-f79fb43a340f
0
avalia.lua
file
15
deleted
bible.txt
file
15
deleted
bible2.txt
file
15
deleted
cicle.lua
file
15
2011-08-09T17:53:37.000000Z
25d995ed26b10a3f76f9815400ad66e5
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
1525
ciclo.lua
file
15
deleted
ciclo2.lua
file
15
deleted
conta_palavras.lua
file
15
deleted
dupfinalizer.lua
file
15
2011-08-09T17:53:40.000000Z
edefd33164da4527386c9b6d5357706d
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
695
duplicata.lua
file
15
deleted
eval.lua
file
15
2011-08-09T17:53:47.000000Z
d1a86c5c2bc120b9f99e72fd38789a1b
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
438
function.lua
file
15
2011-08-09T17:53:50.000000Z
3f0e2ae45aad543406d1292166eb90a6
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
759
out
dir
rec.lua
file
9
deleted
resources
dir
string.lua
file
15
2011-08-09T17:53:54.000000Z
6094d4bdd9a7db1cf5e7bd33d1649274
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
482
table.lua
file
15
2011-08-09T17:53:57.000000Z
b3f34f4247c7c00aa4b9272181c2f57b
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
507
test.lua
file
9
deleted
wfc.lua
file
15
2011-08-09T17:54:01.000000Z
5bccea8a261518ff0d724ba8193b63c0
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
1370

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,91 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
local function aux_cicle (ntab, tab, aux_tab)
aux_tab[ntab] = 1
for k,v in pairs(ntab) do
if v == tab then
return true
end
if type(v) == "table" and not aux_tab[v] then
return aux_cicle(v, tab, aux_tab)
end
end
return false
end
function cicle(tab)
if tab then
return aux_cicle(tab, tab, {})
else
return false
end
end
a = {x = {}}; a.x[4] = a
cicle(a)
a = {x = {}}; a.x[4] = a.x
cicle(a)
a = {x = {}};
a.x[4] = a.x
a.x[5] = x
b = {c = {a}}
a.x = b
cicle(a)
lmp.stop()
lmp.start(...)
local function aux_cicle2(ntab, tab, aux_tab)
aux_tab[ntab] = 1
for k,v in pairs(ntab) do
if v == tab then
return true
end
if type(v) == "table" and not aux_tab[v] then
local tmp = aux_cicle2(v, tab, aux_tab, tmp)
if tmp then
if type(tmp) == "table" then
table.insert(tmp, k)
else
tmp = {k}
end
end
return tmp
end
end
return false
end
function cicle2(tab)
if tab then
local res = {}
local tmp = aux_cicle2(tab, tab, {})
if tmp then
local i = #tmp
for _,v in ipairs(tmp) do
res[i] = v
i = i - 1;
end
return res
end
end
return false
end
a = {x = {}}; a.x[4] = a
cicle2(a)
a = {x = {}}; a.x[4] = a.x
cicle2(a)
a = {x = {}};
a.x[4] = a.x
a.x[5] = x
b = {c = {a}}
a.x = b
cicle2(a)
lmp.stop()

View File

@ -0,0 +1,31 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
function duplic (str)
local str_tab = {}
for v in string.gmatch(str, "%w+") do
if str_tab[v] then
return v
else
str_tab[v] = 1
end
end
return nil
end
local str = [[
This version of the King James Bible was created by taking several
public domain copies and painstakingly comparing them to find all
the differences, and selecting the most common version. Each of the
differences was also compared to printed versions for verification.
]]
duplic("")
duplic("um dois tres dois um")
duplic("um dois tres quatro")
duplic(str)

View File

@ -0,0 +1,25 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
function eval(str)
local tab = {}
local f = loadstring("local x=...; return "..str)
for i=0,10 do
a,b = pcall(f,i)
if not a then
return a,b
else
tab[i] = b
end
end
return tab
end
for k,v in pairs(eval("10*x^4 - 5*x^3 + 7*x^2 - 3*x + 5")) do ; end
lmp.stop()

View File

@ -0,0 +1,40 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
local function x() end
lmp.stop()
lmp.start(...)
local function x() end
local function y() end
lmp.stop()
lmp.start(...)
local function x() print("teste") end
local function y() end
lmp.stop()
lmp.start(...)
local function x() print("teste"); print("funcao");end
local function y() end
lmp.stop()
lmp.start(...)
local function x() print("teste"); end
local function y() x(); end
lmp.stop()
lmp.start(...)
local function x() print("teste"); end
local function y() print("teste"); y(); end
lmp.stop()
lmp.start(...)
local function x() print("teste"); end
local function y() print("teste"); y(); x(); end
lmp.stop()

View File

@ -0,0 +1,28 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
-- pre-defined strings do not use malloc
local a = ""
local b = "t"
local c = "a"
local d = "tamanho8"
local e = "tamanhotamanhotamanhotamanhotamanhotamanhotamanhotamanhotamanho65"
lmp.start(...)
assert((a..b))
lmp.stop()
lmp.start(...)
assert((b..c))
lmp.stop()
lmp.start(...)
assert((b..c..d))
lmp.stop()
lmp.start(...)
assert((b..c..d..e))
lmp.stop()

View File

@ -0,0 +1,38 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
local t = {}
lmp.stop()
lmp.start(...)
local t = {10}
lmp.stop()
lmp.start(...)
local t = {10, 20, 30}
lmp.stop()
lmp.start(...)
local t = {}
for i=10,200,10 do
table.insert(t, i)
end
lmp.stop()
lmp.start(...)
local t = {}
for i=10,320,10 do
table.insert(t, i)
end
lmp.stop()
lmp.start(...)
local t = {}
for i=10,330,10 do
table.insert(t, i)
end
lmp.stop()

View File

@ -0,0 +1,54 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
function allwords ()
local line = io.read() -- current line
local pos = 1 -- current position in the line
return function () -- iterator function
while line do -- repeat while there are lines
local s, e = string.find(line, "%w+", pos)
if s then -- found a word?
pos = e + 1 -- next position is after this word
return string.sub(line, s, e) -- return the word
else
line = io.read() -- word not found; try next line
pos = 1 -- restart from first position
end
end
return nil -- no more lines: end of traversal
end
end
function word_count(f, max)
local tab,k,result,word,n = {},0,{}
io.input(f)
for word in allwords() do
if tab[word] then
tab[word].qtd = tab[word].qtd + 1
else
tab[word] = {}
tab[word].qtd = 1
tab[word].palavra = word
end
end
for k,n in pairs(tab) do table.insert(result,n) end
table.sort(result, function (a, b)
return a.qtd > b.qtd
end )
local b=0;
-- print(#result)
for k,v in ipairs(result) do
if b ==max then return end
b = b+1
-- print(v.palavra,v.qtd)
end
end
local old_in = io.input()
word_count("tests/resources/wfc_bible.txt", 10)
io.input(old_in)
lmp.stop()

91
tests/cicle.lua Normal file
View File

@ -0,0 +1,91 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
local function aux_cicle (ntab, tab, aux_tab)
aux_tab[ntab] = 1
for k,v in pairs(ntab) do
if v == tab then
return true
end
if type(v) == "table" and not aux_tab[v] then
return aux_cicle(v, tab, aux_tab)
end
end
return false
end
function cicle(tab)
if tab then
return aux_cicle(tab, tab, {})
else
return false
end
end
a = {x = {}}; a.x[4] = a
cicle(a)
a = {x = {}}; a.x[4] = a.x
cicle(a)
a = {x = {}};
a.x[4] = a.x
a.x[5] = x
b = {c = {a}}
a.x = b
cicle(a)
lmp.stop()
lmp.start(...)
local function aux_cicle2(ntab, tab, aux_tab)
aux_tab[ntab] = 1
for k,v in pairs(ntab) do
if v == tab then
return true
end
if type(v) == "table" and not aux_tab[v] then
local tmp = aux_cicle2(v, tab, aux_tab, tmp)
if tmp then
if type(tmp) == "table" then
table.insert(tmp, k)
else
tmp = {k}
end
end
return tmp
end
end
return false
end
function cicle2(tab)
if tab then
local res = {}
local tmp = aux_cicle2(tab, tab, {})
if tmp then
local i = #tmp
for _,v in ipairs(tmp) do
res[i] = v
i = i - 1;
end
return res
end
end
return false
end
a = {x = {}}; a.x[4] = a
cicle2(a)
a = {x = {}}; a.x[4] = a.x
cicle2(a)
a = {x = {}};
a.x[4] = a.x
a.x[5] = x
b = {c = {a}}
a.x = b
cicle2(a)
lmp.stop()

31
tests/dupfinalizer.lua Normal file
View File

@ -0,0 +1,31 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
function duplic (str)
local str_tab = {}
for v in string.gmatch(str, "%w+") do
if str_tab[v] then
return v
else
str_tab[v] = 1
end
end
return nil
end
local str = [[
This version of the King James Bible was created by taking several
public domain copies and painstakingly comparing them to find all
the differences, and selecting the most common version. Each of the
differences was also compared to printed versions for verification.
]]
duplic("")
duplic("um dois tres dois um")
duplic("um dois tres quatro")
duplic(str)

25
tests/eval.lua Normal file
View File

@ -0,0 +1,25 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
function eval(str)
local tab = {}
local f = loadstring("local x=...; return "..str)
for i=0,10 do
a,b = pcall(f,i)
if not a then
return a,b
else
tab[i] = b
end
end
return tab
end
for k,v in pairs(eval("10*x^4 - 5*x^3 + 7*x^2 - 3*x + 5")) do ; end
lmp.stop()

40
tests/function.lua Normal file
View File

@ -0,0 +1,40 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
local function x() end
lmp.stop()
lmp.start(...)
local function x() end
local function y() end
lmp.stop()
lmp.start(...)
local function x() print("teste") end
local function y() end
lmp.stop()
lmp.start(...)
local function x() print("teste"); print("funcao");end
local function y() end
lmp.stop()
lmp.start(...)
local function x() print("teste"); end
local function y() x(); end
lmp.stop()
lmp.start(...)
local function x() print("teste"); end
local function y() print("teste"); y(); end
lmp.stop()
lmp.start(...)
local function x() print("teste"); end
local function y() print("teste"); y(); x(); end
lmp.stop()

417
tests/out/.svn/entries Normal file
View File

@ -0,0 +1,417 @@
10
dir
9
http://subversion.assembla.com/svn/luamemprofiler/trunk/tests/out
http://subversion.assembla.com/svn/luamemprofiler
2011-06-20T22:55:47.091878Z
9
pablomusa
svn:special svn:externals svn:needs-lock
2addb8f8-2ff2-4263-acf2-f79fb43a340f
0
avalia.txt
file
15
deleted
cicle.txt
file
15
2011-08-09T17:27:59.000000Z
f8d8fe483f65e72e95220843cc196c3e
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
916
ciclo.txt
file
15
deleted
ciclo2.txt
file
15
deleted
conta_palavras.txt
file
15
deleted
dup_finalizer.txt
file
16
deleted
dupfinalizer.txt
file
16
2011-06-20T21:46:03.000000Z
72b91c74b1bd24b14e4fc011ecd09ab2
2011-08-09T19:10:26.449264Z
16
pablomusa
has-props
459
duplicata.txt
file
15
deleted
eval.txt
file
15
2011-06-20T21:44:06.000000Z
de6c4f6b41590e24e83d799722351509
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
461
function.txt
file
2011-06-20T21:40:51.000000Z
9ad5def297695be6fbb16b7a3b83faf5
2011-06-20T22:55:47.091878Z
9
pablomusa
has-props
3143
string.txt
file
2011-06-20T21:40:36.000000Z
e94d12fc08339e5721e4bdaed76fbc09
2011-06-20T22:55:47.091878Z
9
pablomusa
has-props
1729
table.txt
file
2011-06-20T21:41:04.000000Z
4b58156404e846bf344ea019c0cf10bb
2011-06-20T22:55:47.091878Z
9
pablomusa
has-props
2703
wfc.txt
file
21
2011-08-23T05:29:07.000000Z
fd9d4b31d58ea64d86bec66c30f24299
2011-08-23T08:46:53.512517Z
21
pablomusa
has-props
483

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

View File

@ -0,0 +1,24 @@
===================================================================
Number of Mallocs=30 Total Malloc Size=1048
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=5 Total Free Size=168
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=11 | Other=17
Maximum Memory Used=936 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=44 Total Malloc Size=1444
Number of Reallocs=1 Total Realloc Size=12
Number of Frees=6 Total Free Size=196
Number of Allocs of Each Type:
String=1 | Function=2 | Usedata=0 | Thread=0 | Table=16 | Other=25
Maximum Memory Used=1288 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,12 @@
===================================================================
Number of Mallocs=45 Total Malloc Size=3040
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=9 Total Free Size=1036
Number of Allocs of Each Type:
String=24 | Function=5 | Usedata=0 | Thread=0 | Table=4 | Other=12
Maximum Memory Used=2366 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,12 @@
===================================================================
Number of Mallocs=30 Total Malloc Size=1362
Number of Reallocs=14 Total Realloc Size=224
Number of Frees=11 Total Free Size=600
Number of Allocs of Each Type:
String=3 | Function=2 | Usedata=0 | Thread=0 | Table=2 | Other=23
Maximum Memory Used=1014 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,84 @@
===================================================================
Number of Mallocs=1 Total Malloc Size=16
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=1 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=16 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=32
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=32 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=36
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=36 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=36
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=36 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=3 Total Malloc Size=64
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=1
Maximum Memory Used=64 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=3 Total Malloc Size=68
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=1
Maximum Memory Used=68 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=4 Total Malloc Size=96
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=2
Maximum Memory Used=96 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,46 @@
===================================================================
Number of Mallocs=0 Total Malloc Size=0
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=0 bytes
===================================================================
===================================================================
Number of Mallocs=1 Total Malloc Size=19
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=1 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=19 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=1 Total Malloc Size=27
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=1 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=27 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=1 Total Malloc Size=92
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=1 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=92 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,72 @@
===================================================================
Number of Mallocs=1 Total Malloc Size=32
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=0
Maximum Memory Used=32 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=44 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=68
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=68 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=5 Total Realloc Size=372
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=416 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=5 Total Realloc Size=372
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=416 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=6 Total Realloc Size=756
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=800 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,12 @@
===================================================================
Number of Mallocs=13975 Total Malloc Size=854463
Number of Reallocs=12 Total Realloc Size=49140
Number of Frees=3517 Total Free Size=253536
Number of Allocs of Each Type:
String=6137 | Function=4 | Usedata=1 | Thread=0 | Table=2606 | Other=5227
Maximum Memory Used=650067 bytes
We suggest you run the application again using 1.7 as parameter
===================================================================

24
tests/out/cicle.txt Normal file
View File

@ -0,0 +1,24 @@
===================================================================
Number of Mallocs=30 Total Malloc Size=1048
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=5 Total Free Size=168
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=11 | Other=17
Maximum Memory Used=936 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=44 Total Malloc Size=1444
Number of Reallocs=1 Total Realloc Size=12
Number of Frees=6 Total Free Size=196
Number of Allocs of Each Type:
String=1 | Function=2 | Usedata=0 | Thread=0 | Table=16 | Other=25
Maximum Memory Used=1288 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

View File

@ -0,0 +1,12 @@
===================================================================
Number of Mallocs=45 Total Malloc Size=3040
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=9 Total Free Size=1036
Number of Allocs of Each Type:
String=24 | Function=5 | Usedata=0 | Thread=0 | Table=4 | Other=12
Maximum Memory Used=2366 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

12
tests/out/eval.txt Normal file
View File

@ -0,0 +1,12 @@
===================================================================
Number of Mallocs=30 Total Malloc Size=1362
Number of Reallocs=14 Total Realloc Size=224
Number of Frees=11 Total Free Size=600
Number of Allocs of Each Type:
String=3 | Function=2 | Usedata=0 | Thread=0 | Table=2 | Other=23
Maximum Memory Used=1014 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

84
tests/out/function.txt Normal file
View File

@ -0,0 +1,84 @@
===================================================================
Number of Mallocs=1 Total Malloc Size=16
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=1 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=16 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=32
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=32 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=36
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=36 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=36
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=36 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=3 Total Malloc Size=64
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=1
Maximum Memory Used=64 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=3 Total Malloc Size=68
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=1
Maximum Memory Used=68 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=4 Total Malloc Size=96
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=2 | Usedata=0 | Thread=0 | Table=0 | Other=2
Maximum Memory Used=96 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

46
tests/out/string.txt Normal file
View File

@ -0,0 +1,46 @@
===================================================================
Number of Mallocs=0 Total Malloc Size=0
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=0 bytes
===================================================================
===================================================================
Number of Mallocs=1 Total Malloc Size=19
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=1 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=19 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=1 Total Malloc Size=27
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=1 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=27 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=1 Total Malloc Size=92
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=1 | Function=0 | Usedata=0 | Thread=0 | Table=0 | Other=0
Maximum Memory Used=92 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

72
tests/out/table.txt Normal file
View File

@ -0,0 +1,72 @@
===================================================================
Number of Mallocs=1 Total Malloc Size=32
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=0
Maximum Memory Used=32 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=44 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=68
Number of Reallocs=0 Total Realloc Size=0
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=68 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=5 Total Realloc Size=372
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=416 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=5 Total Realloc Size=372
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=416 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================
===================================================================
Number of Mallocs=2 Total Malloc Size=44
Number of Reallocs=6 Total Realloc Size=756
Number of Frees=0 Total Free Size=0
Number of Allocs of Each Type:
String=0 | Function=0 | Usedata=0 | Thread=0 | Table=1 | Other=1
Maximum Memory Used=800 bytes
We suggest you run the application again using 0.6 as parameter
===================================================================

12
tests/out/wfc.txt Normal file
View File

@ -0,0 +1,12 @@
===================================================================
Number of Mallocs=13975 Total Malloc Size=854463
Number of Reallocs=12 Total Realloc Size=49140
Number of Frees=3517 Total Free Size=253536
Number of Allocs of Each Type:
String=6137 | Function=4 | Usedata=1 | Thread=0 | Table=2606 | Other=5227
Maximum Memory Used=650067 bytes
We suggest you run the application again using 1.7 as parameter
===================================================================

View File

@ -0,0 +1,69 @@
10
dir
15
http://subversion.assembla.com/svn/luamemprofiler/trunk/tests/resources
http://subversion.assembla.com/svn/luamemprofiler
2011-08-09T19:03:59.875069Z
15
pablomusa
svn:special svn:externals svn:needs-lock
2addb8f8-2ff2-4263-acf2-f79fb43a340f
0
wfc_bible.txt
file
2011-06-15T20:24:47.000000Z
473241bce157f97081c82e381dcefd94
2011-08-09T19:03:59.875069Z
15
pablomusa
has-props
208926

View File

@ -0,0 +1,5 @@
K 13
svn:eol-style
V 6
native
END

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

28
tests/string.lua Normal file
View File

@ -0,0 +1,28 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
-- pre-defined strings do not use malloc
local a = ""
local b = "t"
local c = "a"
local d = "tamanho8"
local e = "tamanhotamanhotamanhotamanhotamanhotamanhotamanhotamanhotamanho65"
lmp.start(...)
assert((a..b))
lmp.stop()
lmp.start(...)
assert((b..c))
lmp.stop()
lmp.start(...)
assert((b..c..d))
lmp.stop()
lmp.start(...)
assert((b..c..d..e))
lmp.stop()

38
tests/table.lua Normal file
View File

@ -0,0 +1,38 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
local t = {}
lmp.stop()
lmp.start(...)
local t = {10}
lmp.stop()
lmp.start(...)
local t = {10, 20, 30}
lmp.stop()
lmp.start(...)
local t = {}
for i=10,200,10 do
table.insert(t, i)
end
lmp.stop()
lmp.start(...)
local t = {}
for i=10,320,10 do
table.insert(t, i)
end
lmp.stop()
lmp.start(...)
local t = {}
for i=10,330,10 do
table.insert(t, i)
end
lmp.stop()

54
tests/wfc.lua Normal file
View File

@ -0,0 +1,54 @@
-- Author: Pablo Musa
-- Creation Date: jun 20 2011
-- Last Modification: aug 09 2011
local lmp = require"luamemprofiler"
lmp.start(...)
function allwords ()
local line = io.read() -- current line
local pos = 1 -- current position in the line
return function () -- iterator function
while line do -- repeat while there are lines
local s, e = string.find(line, "%w+", pos)
if s then -- found a word?
pos = e + 1 -- next position is after this word
return string.sub(line, s, e) -- return the word
else
line = io.read() -- word not found; try next line
pos = 1 -- restart from first position
end
end
return nil -- no more lines: end of traversal
end
end
function word_count(f, max)
local tab,k,result,word,n = {},0,{}
io.input(f)
for word in allwords() do
if tab[word] then
tab[word].qtd = tab[word].qtd + 1
else
tab[word] = {}
tab[word].qtd = 1
tab[word].palavra = word
end
end
for k,n in pairs(tab) do table.insert(result,n) end
table.sort(result, function (a, b)
return a.qtd > b.qtd
end )
local b=0;
-- print(#result)
for k,v in ipairs(result) do
if b ==max then return end
b = b+1
-- print(v.palavra,v.qtd)
end
end
local old_in = io.input()
word_count("tests/resources/wfc_bible.txt", 10)
io.input(old_in)
lmp.stop()

702
vmemory.c Normal file
View File

@ -0,0 +1,702 @@
/*
**
** Author: Pablo Musa
** Creation Date: mar 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** See vmemory.h for module overview
**
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <lualib.h>
#include <math.h>
#include "graphic.h"
#include "vmemory.h"
#include "lmp_struct.h"
#include "lmp.h"
#define WINDOW_TITLE "luamemprofiler v1.0"
#define ICON_PATH "logo.bmp"
/* screen state */
#define LMP_PAUSE 0
#define LMP_CONT 1
#define LMP_ZOOM_OUT 0
#define LMP_ZOOM_IN 1
#define MIN_mb_SIZE 1
#define MIN_mb_WIDTH 800
#define MIN_mb_HEIGHT 600
#define BOX_XINI 10 /* MINIMUM = 10 */
#define BOX_YINI 10 /* MINIMUM = 10 */
#define BOX_XEND (mb_width + BOX_XINI)
#define BOX_YEND (mb_height + BOX_YINI)
#define RTCOLUMN_WIDTH 150 /* right column width */
#define BTROW_HEIGHT 70 /* bottom row height */
#define BASE_SPACE 10 /* space for separating text from the box */
#define BOX_BORDER 3 /* memory box border width */
#define LMP_FLINE 0 /* bottom row starts writing in first line (0) */
#define LMP_ON 1
#define LMP_OFF 0
/* filter type menu - positions to draw, bool toggled, draw Color, and text */
struct menuitem {
int x;
int y;
int toggle;
Color color;
const char *name;
};
typedef struct menuitem LMP_Menuitem;
/* GLOBAL VARIABLES */
/* one block list for each filter type */
extern lmp_Block *lmp_string;
extern lmp_Block *lmp_function;
extern lmp_Block *lmp_userdata;
extern lmp_Block *lmp_thread;
extern lmp_Block *lmp_table;
extern lmp_Block *lmp_other;
extern lmp_Block *lmp_all;
/* one menu for each filter type */
static LMP_Menuitem mi_string;
static LMP_Menuitem mi_function;
static LMP_Menuitem mi_userdata;
static LMP_Menuitem mi_thread;
static LMP_Menuitem mi_table;
static LMP_Menuitem mi_other;
/* STATIC GLOBAL VARIABLES */
static Screen *screen;
static int laddress; /* first address of the program */
static int baseaddr; /* base address of the memory box */
static int state = LMP_PAUSE; /* luamemprofiler state (paused or executing) */
static int zoom = LMP_ZOOM_OUT; /* zoom state (in or out) */
static int sc_width; /* sc = screen */
static int sc_height;
static int mb_width; /* mb = memory box */
static int mb_height;
static int BYTES_PER_PIXEL = 4;
static int BLOCK_HEIGHT = 2;
static int statesy; /* used to update the display with state and zoom */
/* STATIC FUNCTIONS */
static void drawbtrow();
static void toggleall();
static void drawstates();
static void drawmembox();
static void checkevent();
static void clearmembox();
static void untoggleall();
static int istoggled(size_t luatype);
static void drawcallstack(int fline);
static void drawrtcolumn(float memused);
static int setcanvassize (float memused);
static void inverttoggle(LMP_Menuitem *mi);
static void drawmenuitem(LMP_Menuitem *item);
static void drawreport(const char *text, int line);
static void drawmemblock(int addr, size_t luatype, size_t size);
static void writeblockinfo(void *ptr,size_t luatype,size_t size,int alloctype);
static void calcmemdata(void *ptr, size_t size, int *reladdr, size_t *relsize);
static void initmenuitem(LMP_Menuitem *mi, int x, int y, int toggle,
Color color, const char* name);
/* GLOBAL FUNCTIONS */
void vm_start(int lowestaddress, float memused) {
/* if memused is very low uses default value and returns it */
memused = setcanvassize (memused);
screen = gr_newscreen(sc_width, sc_height, ICON_PATH, WINDOW_TITLE);
laddress = lowestaddress;
baseaddr = laddress;
gr_drawbackground(screen, LMP_VM_BACKGROUND_CL);
drawmembox();
drawrtcolumn(memused);
drawbtrow();
checkevent();
}
void vm_stop() {
char dummy;
state = 0;
drawreport("Execution finished. The report is in the Terminal.", LMP_FLINE);
printf("Press Enter To Finish!");
scanf("%c", &dummy);
gr_destroyscreen(screen);
}
void vm_newmemop(int memop, void *ptr, size_t luatype, size_t size) {
int p;
size_t mb_size;
calcmemdata(ptr, size, &p, &mb_size); /* calculate relative address */
if (p > 0) { /* check if is a valid address */
/* draw full block breaking lines if necessary */
if (istoggled(luatype))
drawmemblock(p, luatype, mb_size);
if (state == LMP_PAUSE) {
/* write in 'bottom row' block information(parameters) and call stack */
writeblockinfo(ptr, luatype, size, memop);
}
/* check if there is any valid event and treat it */
checkevent();
}
/* DEBUG else { possible print if block is smaller than baseaddress
printf("Lower Pointer ptr=%d laddr=%d p=%d\n", (int) ptr, laddress, p);
} */
}
/* STATIC FUNCTIONS */
/* uses baseaddress to calculate the memory box position of a block */
static void calcmemdata(void *ptr, size_t size, int *reladdr, size_t *relsize) {
*reladdr = ((int) ptr - baseaddr) / BYTES_PER_PIXEL;
*relsize = (size / BYTES_PER_PIXEL);
if (*relsize == 0) {
*relsize = 1;
}
}
/* draw specified text in report area (botton row) */
static void drawreport(const char *text, int line) {
int x = BOX_XINI;
int y = BOX_YEND + BASE_SPACE + (line * gr_gettextheight(screen));
/* if line does not fit screen size, omit line */
if (y > sc_height - gr_gettextheight(screen)) {
return;
}
/* if line is first line, new message -> clear bottom row */
if (line == LMP_FLINE) {
gr_setdrawcolor(screen, LMP_VM_BACKGROUND_CL);
gr_drawblock(screen, BOX_XINI, BOX_XEND, BOX_YEND+BASE_SPACE, BTROW_HEIGHT);
}
/* validate text size */
if (strlen(text) > (mb_width / gr_gettextwidth(screen))) {
gr_drawtext(screen, "Sorry, but the text is too large.", x, y);
} else {
gr_drawtext(screen, text, x, y);
}
}
/* draw up to 3 levels of the call stack */
static void drawcallstack(int fline) {
char textbuff[80] = "";
int res, i = 0;
lua_Debug ld;
lua_State *L = (lua_State *) laddress;
res = lua_getstack(L, i, &ld);
while (res == 1 && i < (BTROW_HEIGHT/gr_gettextwidth(screen))) {
int r;
r = lua_getinfo(L, "lnS", &ld);
if (r != 0) {
int line = LMP_FLINE + i + fline; /* start in fline */
if (strcmp(ld.what, "main") == 0) { /* main program execution */
sprintf(textbuff, "Main - line:%d", ld.currentline);
drawreport(textbuff, line);
break;
}
if (strcmp(ld.what, "Lua") == 0) { /* some function execution */
sprintf(textbuff, "Lua - file:'%s' func:'%s' field:'%s' line:%d",
ld.short_src, ld.name, ld.namewhat, ld.currentline);
drawreport(textbuff, line);
}
if (strcmp(ld.what, "C") == 0) { /* some C function execution */
sprintf(textbuff, "C - func'%s' field:'%s'", ld.name, ld.namewhat);
drawreport(textbuff, line);
}
} else {
printf("luamemprofiler internal error: vmemory -> debuginfo -> invalid what.\n");
exit(EXIT_FAILURE);
}
i++;
res = lua_getstack(L, i, &ld);
}
}
/* draw blocks in the correct place (recursive calls for big blocks) */
static void drawmemblock(int addr, size_t luatype, size_t size) {
int x, y;
x = (addr % mb_width) + BOX_XINI;
y = ((addr / mb_width) * BLOCK_HEIGHT) + BOX_YINI;
/* just draw into valid areas */
if (y >= BOX_YINI && (y + BLOCK_HEIGHT) <= BOX_YEND) {
if (x + size > BOX_XEND){ /* break block to fit membox */
size_t extrasize = size - (BOX_XEND + 1 - x); /* +1 -> XEND is valid */
size = size - extrasize;
/* recursive call for breaking one block in different lines */
drawmemblock(addr + (size - 1), luatype, extrasize); /* -1 -> XEND */
}
switch(luatype) {
case LUA_TSTRING:
gr_setdrawcolor(screen, LMP_VM_STRING_CL);
break;
case LUA_TFUNCTION:
gr_setdrawcolor(screen, LMP_VM_FUNCTION_CL);
break;
case LUA_TUSERDATA:
gr_setdrawcolor(screen, LMP_VM_USERDATA_CL);
break;
case LUA_TTHREAD:
gr_setdrawcolor(screen, LMP_VM_THREAD_CL);
break;
case LUA_TTABLE:
gr_setdrawcolor(screen, LMP_VM_TABLE_CL);
break;
case LUA_TFREE:
gr_setdrawcolor(screen, LMP_VM_FREE_CL);
break;
default:
gr_setdrawcolor(screen, LMP_VM_OTHER_CL);
}
/* block length is size, so draw from x to "size-1" */
gr_drawblock(screen, x, x + size - 1, y, BLOCK_HEIGHT);
}
/* DEBUG else { possible use when all blocks have to be drawn
printf("draw block (%d, %d) addr = %d\n", x, y, addr); } */
}
/*
** traverse a filter list drawing all blocks. 'block' is the first block in the
** list and 'fnextblock' is a function that returns the next block in the list
** or NULL
*/
void drawblocklist(lmp_Block *block, lmp_Block* (*fnextblock) (lmp_Block*)) {
int p;
size_t mb_size;
while (block != NULL) { /* list is not empty */
calcmemdata(block->ptr, st_getsize(block), &p, &mb_size);
if (p > 0) {
int luatype = istoggled(block->luatype) ? block->luatype : LUA_TFREE;
drawmemblock(p, luatype, mb_size);
}
block = fnextblock(block);
}
}
/*
** redraw blocks using bigger size and new baseaddress. The new base address is
** calculated using 'y' coordinate. All blocks above this 'y' (y included) are
** redrawn.
*/
static void zoomin(int x, int y) {
int p;
size_t mb_size;
lmp_Block *block;
zoom = LMP_ZOOM_IN; /* change zoom state */
drawstates(); /* update display with new state */
clearmembox(); /* clear memory box for new blocks in zoom mode */
/* calculates baseaddress using old baseaddress and 'y' */
baseaddr = (((y - BOX_YINI) / BLOCK_HEIGHT) * (mb_width)
* BYTES_PER_PIXEL) + baseaddr;
BYTES_PER_PIXEL = BYTES_PER_PIXEL / 2; /* width 2x bigger */
BLOCK_HEIGHT = BLOCK_HEIGHT * 2; /* height 2x bigger */
for(block = lmp_all; block != NULL; block = st_getnextall(block)) {
/* calculates new block values in memry box (relative address and size) */
p = ((int) block->ptr - baseaddr) / BYTES_PER_PIXEL;
mb_size = (block->size / BYTES_PER_PIXEL);
if (mb_size == 0) {
mb_size = 1;
}
/* check if block is inside zoom */
if (istoggled(block->luatype) && p >= 0 &&
p <= (mb_width * BYTES_PER_PIXEL) * (mb_height / BLOCK_HEIGHT)) {
drawmemblock(p, block->luatype, mb_size);
}
}
}
/* redraw blocks using smaller size and old baseaddress. */
static void zoomout() {
zoom = LMP_ZOOM_OUT; /* change zoom state */
drawstates(); /* update display with new state */
clearmembox(); /* clear memory box for new blocks without zoom mode */
BYTES_PER_PIXEL = BYTES_PER_PIXEL * 2; /* width 2x smaller */
BLOCK_HEIGHT = BLOCK_HEIGHT / 2; /* height 2x smaller */
baseaddr = laddress; /* restore baseaddress */
drawblocklist(lmp_all, st_getnextall); /* draw all blocks */
}
static void checkevent() {
int eventtype;
LMP_Event event;
if (state == LMP_CONT) { /* normal execution - only accepts pause command */
eventtype = gr_getevent(screen, &event); /* gets an event if exists */
if (eventtype == LMP_EVENT_KEY && event.kevent.key == ' ') { /* pause */
state = LMP_PAUSE;
drawstates(); /* update display with new state */
drawreport("Press: 'space' to resume execution; 'n' to resume until next memory operation;", LMP_FLINE);
drawreport("'c' to clear the memory box; 's,f,u,h,t,o' to redraw blocks of specific type;", LMP_FLINE + 1);
drawreport("'a' to redraw all blocks; left-click for zoom in and right-click for zoom out.", LMP_FLINE + 2);
}
}
while (state == LMP_PAUSE) { /* execution is paused */
lmp_Block* (*fnextblock) (lmp_Block*) = st_getnexttype;
lmp_Block *block = NULL;
eventtype = gr_waitevent(screen, &event); /* wait for a valid event */
if (eventtype == LMP_EVENT_KEY) {
switch (event.kevent.key) {
case ' ': /* space key - continue - resumes normal execution */
state = LMP_CONT;
drawstates();
drawreport("Press 'space' to Pause execution.", LMP_FLINE);
return;
case 'n': /* next - execute next memory operation */
return;
case 's': /* draw filter type - set correct list and toggle */
inverttoggle(&mi_string);
block = lmp_string;
break;
case 'f':
inverttoggle(&mi_function);
block = lmp_function;
break;
case 'u':
inverttoggle(&mi_userdata);
block = lmp_userdata;
break;
case 'h':
inverttoggle(&mi_thread);
block = lmp_thread;
break;
case 't':
inverttoggle(&mi_table);
block = lmp_table;
break;
case 'o':
inverttoggle(&mi_other);
block = lmp_other;
break;
case 'a': /* draw all blocks */
toggleall();
block = lmp_all;
fnextblock = st_getnextall;
break;
case 'c': /* erase all blocks from memory box */
untoggleall();
clearmembox();
}
drawblocklist(block, fnextblock);
} else if (eventtype == LMP_EVENT_MOUSE) {
if (event.mevent.b == LEFT_BUTTON && zoom == LMP_ZOOM_OUT) {
zoomin(event.mevent.x, event.mevent.y);
} else if (event.mevent.b == RIGHT_BUTTON && zoom == LMP_ZOOM_IN) {
zoomout();
}
}
}
}
/*
** write in bottom row the memory operation and the block info.
** block info = allocation type, block (address, type and size) and call stack
*/
static void writeblockinfo(void *ptr, size_t luatype, size_t size, int alloctype) {
char textbuff[60];
char ltype[9];
char atype[8];
switch(luatype) {
case LUA_TSTRING:
strcpy(ltype, "String");
break;
case LUA_TFUNCTION:
strcpy(ltype, "Function");
break;
case LUA_TUSERDATA:
strcpy(ltype, "Userdata");
break;
case LUA_TTHREAD:
strcpy(ltype, "Thread");
break;
case LUA_TTABLE:
strcpy(ltype, "Table");
break;
default:
strcpy(ltype, "Other");
break;
}
switch(alloctype) {
case LMP_VM_FREE:
strcpy(atype, "Free");
break;
case LMP_VM_MALLOC:
strcpy(atype, "Malloc");
break;
case LMP_VM_REALLOC:
strcpy(atype, "Realloc");
break;
}
sprintf(textbuff, "%s | addr = %p | type = %s | size = %dB", atype,
ptr, ltype, size);
drawreport(textbuff, LMP_FLINE);
drawcallstack(LMP_FLINE + 1);
}
/* draw border lines and clear memory box */
static void drawmembox() {
int i;
gr_setdrawcolor(screen, BLACK);
for (i = 1; i <= BOX_BORDER; i++) {
int x1 = BOX_XINI - i, x2 = BOX_XEND + i;
int y1 = BOX_YINI - i, y2 = BOX_YEND + i;
gr_drawline(screen, x1, y1, x2, y1);
gr_drawline(screen, x1, y2, x2, y2);
gr_drawline(screen, x1, y1, x1, y2);
gr_drawline(screen, x2, y1, x2, y2);
}
clearmembox();
}
/* draw one item of the right column */
static void drawmenuitem(LMP_Menuitem *item) {
int offset = gr_gettextwidth(screen) * strlen(item->name) + 3;
int bx = item->x + offset;
int by = item->y + 4;
gr_settextcolor(screen, BLACK);
gr_drawtext(screen, item->name, item->x, item->y);
if (item->toggle) {
gr_setdrawcolor(screen, item->color);
gr_drawblock(screen, bx, bx + 10, by, 10);
} else {
gr_setdrawcolor(screen, LMP_VM_BACKGROUND_CL);
gr_drawblock(screen, bx, bx + 10, by, 10);
gr_setdrawcolor(screen, item->color);
gr_drawline(screen, bx, by, bx + 10, by);
gr_drawline(screen, bx, by, bx, by + 10);
gr_drawline(screen, bx, by+ 10, bx + 10, by + 10);
gr_drawline(screen, bx + 10, by, bx + 10, by + 10);
}
}
/* write a line division(black) and a label(red) in (x,y) coordinate */
static int drawl(const char *text, int x, int y) {
int text_width = strlen(text) * gr_gettextwidth(screen);
int center_offset = (RTCOLUMN_WIDTH - (text_width + BASE_SPACE))/2;
gr_setdrawcolor(screen, BLACK);
gr_drawline(screen, x, y, sc_width - BASE_SPACE, y);
y = y + 10;
gr_settextcolor(screen, RED);
gr_drawtext(screen, text, x + center_offset, y);
return y;
}
/* write initial message in the bottom row */
static void drawbtrow() {
gr_settextcolor(screen, BLACK);
drawreport("Welcome to the luamemprofiler library. Press 'space' to run the program", LMP_FLINE);
drawreport("normally or 'n' to execute the program until next memory operation.", LMP_FLINE + 1);
}
/* draw right column, including initial states (paused, zoom in) */
static void drawrtcolumn(float memused) {
int x = BOX_XEND + BOX_BORDER + BASE_SPACE;
int y = BOX_YINI;
int offset = 30;
char textbuff[15];
/* draw basic information */
y = drawl("BASIC INFO", x, y);
y = y + offset;
gr_settextcolor(screen, BLACK);
gr_drawtext(screen, "Memory Size", x, y);
y = y + gr_gettextwidth(screen) + 5;
sprintf(textbuff, "%.1fMb", memused);
gr_drawtext(screen, textbuff, x, y);
y = y + offset;
gr_drawtext(screen, "Granularity", x, y);
y = y + gr_gettextwidth(screen) + 5;
sprintf(textbuff, "1x2 px = %dB", BYTES_PER_PIXEL);
gr_drawtext(screen, textbuff, x, y);
y = y + offset;
/* draw key menu and labels */
y = drawl("COMMANDS", x, y);
y = y + offset;
gr_settextcolor(screen, BLACK);
initmenuitem(&mi_string, x, y, LMP_ON, LMP_VM_STRING_CL, "s - String");
drawmenuitem(&mi_string);
y = y + offset;
initmenuitem(&mi_function, x, y, LMP_ON, LMP_VM_FUNCTION_CL, "f - Function");
drawmenuitem(&mi_function);
y = y + offset;
initmenuitem(&mi_userdata, x, y, LMP_ON, LMP_VM_USERDATA_CL, "u - Userdata");
drawmenuitem(&mi_userdata);
y = y + offset;
initmenuitem(&mi_thread, x, y, LMP_ON, LMP_VM_THREAD_CL, "h - Thread");
drawmenuitem(&mi_thread);
y = y + offset;
initmenuitem(&mi_table, x, y, LMP_ON, LMP_VM_TABLE_CL, "t - Table");
drawmenuitem(&mi_table);
y = y + offset;
initmenuitem(&mi_other, x, y, LMP_ON, LMP_VM_OTHER_CL, "o - Other");
drawmenuitem(&mi_other);
y = y + offset;
gr_drawtext(screen, "a - All", x, y);
y = y + offset;
gr_drawtext(screen, "c - Clear", x, y);
y = y + offset;
gr_drawtext(screen, "n - Next", x, y);
y = y + offset;
/* draw luamemprofiler state and zoom state */
y = drawl("STATE", x, y);
y = y + offset;
statesy = y; /* set where to redraw states */
gr_settextcolor(screen, BLACK);
gr_drawtext(screen, "lmp: PAUSED", x, y);
y = y + offset;
gr_drawtext(screen, "zoom: OUT", x, y);
}
/* update states (pause x execution || [zoom] in x out */
static void drawstates() {
int x = BOX_XEND + BOX_BORDER + BASE_SPACE;
int y = statesy;
int offset = 30;
/* erase old text */
gr_setdrawcolor(screen, LMP_VM_BACKGROUND_CL);
gr_drawblock(screen, x, x + RTCOLUMN_WIDTH, y, 50);
/* write new text */
gr_settextcolor(screen, BLACK);
if(state == LMP_PAUSE) {
gr_drawtext(screen, "lmp: PAUSED", x, y);
} else if (state == LMP_CONT) {
gr_drawtext(screen, "lmp: EXECUTING", x, y);
}
y = y + offset;
if(zoom == LMP_ZOOM_OUT) {
gr_drawtext(screen, "zoom: OUT", x, y);
} else if(zoom == LMP_ZOOM_IN) {
gr_drawtext(screen, "zoom: IN", x, y);
}
}
/* calculates and sets screen and memory box width and height */
static int setcanvassize (float memused) {
if (memused <= (float) MIN_mb_SIZE) {
mb_width = MIN_mb_WIDTH;
mb_height = MIN_mb_HEIGHT;
memused = MIN_mb_SIZE;
} else { /* MAX MEM FOR 800 x 600 resolution */
int side;
if (memused > 1) {
BYTES_PER_PIXEL = ((int) memused) * 4;
}
/* (1Mb * BLOCK_HEIGHT / BYTES_PER_PIXEL / PROPORTION(4:3)) */
side = (int) sqrt(memused*1000000*BLOCK_HEIGHT/BYTES_PER_PIXEL/(4*3))+1;
mb_width = side * 4;
mb_height = side * 3;
}
sc_width = BOX_XINI + mb_width + BOX_BORDER + BASE_SPACE + RTCOLUMN_WIDTH;
sc_height = BOX_YINI + mb_height + BOX_BORDER + BASE_SPACE + BTROW_HEIGHT;
return memused;
}
/* paint all memory box with defined color (erase drawn blocks) */
static void clearmembox() {
gr_setdrawcolor(screen, LMP_VM_MEMBOX_CL);
gr_drawblock(screen, BOX_XINI, BOX_XEND, BOX_YINI, BOX_YEND - BOX_YINI);
}
static int istoggled(size_t luatype) {
switch(luatype) {
case LUA_TSTRING:
return mi_string.toggle;
case LUA_TFUNCTION:
return mi_function.toggle;
case LUA_TUSERDATA:
return mi_userdata.toggle;
case LUA_TTHREAD:
return mi_thread.toggle;
case LUA_TTABLE:
return mi_table.toggle;
default:
return mi_other.toggle;
}
}
static void toggleall() {
mi_string.toggle = LMP_ON;
drawmenuitem(&mi_string);
mi_function.toggle = LMP_ON;
drawmenuitem(&mi_function);
mi_userdata.toggle = LMP_ON;
drawmenuitem(&mi_userdata);
mi_thread.toggle = LMP_ON;
drawmenuitem(&mi_thread);
mi_table.toggle = LMP_ON;
drawmenuitem(&mi_table);
mi_other.toggle = LMP_ON;
drawmenuitem(&mi_other);
}
static void untoggleall() {
mi_string.toggle = LMP_OFF;
drawmenuitem(&mi_string);
mi_function.toggle = LMP_OFF;
drawmenuitem(&mi_function);
mi_userdata.toggle = LMP_OFF;
drawmenuitem(&mi_userdata);
mi_thread.toggle = LMP_OFF;
drawmenuitem(&mi_thread);
mi_table.toggle = LMP_OFF;
drawmenuitem(&mi_table);
mi_other.toggle = LMP_OFF;
drawmenuitem(&mi_other);
}
static void initmenuitem(LMP_Menuitem *mi, int x, int y, int toggle,
Color color, const char* name) {
mi->x = x; mi->y = y; mi->toggle = toggle;
mi->color = color; mi->name = name;
}
/* change toggle settings and redraw menu item */
static void inverttoggle(LMP_Menuitem *mi) {
mi->toggle = !mi->toggle;
drawmenuitem(mi);
}

57
vmemory.h Normal file
View File

@ -0,0 +1,57 @@
/*
**
** Author: Pablo Musa
** Creation Date: mar 27 2011
** Last Modification: aug 22 2011
** See Copyright Notice in COPYRIGHT
**
** This module manages the graphical display offered by the library. It defines
** the size of each element: right column, bottom row, memory box, box border,
** etc. It also dynamically calculates: block's bytes per pixel based on the
** memory consumption; the relative address of each pointer; the x, y
** coordinate to the block; the zoom in and zoom out.
** Finally, this module is responsible by managing the events and the
** corresponding actions.
**
*/
#ifndef LMP_VMEMORY_H
#define LMP_VMEMORY_H
#include "graphic.h"
#define LMP_VM_FREE 0
#define LMP_VM_MALLOC 1
#define LMP_VM_REALLOC 2
#define LUA_TFREE 11
#define LMP_VM_STRING_CL DARKRED
#define LMP_VM_FUNCTION_CL DARKMAGENTA
#define LMP_VM_USERDATA_CL DARKGREEN
#define LMP_VM_THREAD_CL DARKORANGE
#define LMP_VM_TABLE_CL DARKBLUE
#define LMP_VM_OTHER_CL DIMGRAY
#define LMP_VM_FREE_CL WHITE
#define LMP_VM_BACKGROUND_CL LTGRAY
#define LMP_VM_MEMBOX_CL WHITE
/*
** Calculates window size (based on expected memory consumption).
** Initializes the whole window (memory box, bottom row, right column).
*/
void vm_start(int lowestaddress, float memused);
/*
** Calls gr_destroyscreen to destroy the window.
*/
void vm_stop();
/*
** Module main function. It is responsible by managing new memory operations
** and user events.
*/
void vm_newmemop(int memop, void *ptr, size_t luatype, size_t size);
#endif