memory output

This commit is contained in:
John Alanbrook 2024-08-05 15:26:18 -05:00
parent 33d4ebf14a
commit ceb728b1a7
15 changed files with 226 additions and 56 deletions

View file

@ -1,13 +1,40 @@
var actor = {}; var actor = {};
actor.spawn = function(script, config, callback){ var actor_urs = {};
if (typeof script !== 'string') return undefined;
var padawan = Object.create(actor); globalThis.class_use = function(script, config, base, callback)
use(script, padawan); {
if (!actor_urs[script]) {
var newur = Object.create(base);
actor_urs[script] = newur;
}
var padawan = Object.create(actor_urs[script]);
if (callback) callback(padawan);
if (typeof config === 'object') if (typeof config === 'object')
Object.merge(padawan,config); Object.merge(padawan,config);
var file = Resources.find_script(script);
var script = Resources.replstrs(file);
script = `(function() {
var self = this;
var $ = this.__proto__;
${script};
})`;
var fn = os.eval(file,script);
fn.call(padawan);
return padawan;
}
actor.spawn = function(script, config){
if (typeof script !== 'string') return undefined;
var padawan = class_use(script, config, actor);
padawan.padawans = []; padawan.padawans = [];
padawan.timers = []; padawan.timers = [];
padawan.master = this; padawan.master = this;

View file

@ -551,7 +551,7 @@ Object.defineProperty(Object.prototype, 'obscure', {
Object.defineProperty(Object.prototype, 'mixin', { Object.defineProperty(Object.prototype, 'mixin', {
value: function(obj) { value: function(obj) {
if (typeof obj === 'string') if (typeof obj === 'string')
obj = use(obj, this); obj = use(obj);
if (obj) if (obj)
Object.mixin(this, obj); Object.mixin(this, obj);
@ -1418,8 +1418,7 @@ bbox.fromobjs = function(objs)
/* VECTORS */ /* VECTORS */
var Vector = {}; var Vector = {};
Vector.length = function(v) { return Math.hypot(...v); } Vector.length = vector.length;
Vector.norm = vector.norm; Vector.norm = vector.norm;
Vector.project = vector.project; Vector.project = vector.project;
Vector.dot = vector.dot; Vector.dot = vector.dot;

View file

@ -1,5 +1,8 @@
"use math"; "use math";
prosperon.gc_start = function(){}
prosperon.gc_end = function(){}
Object.defineProperty(String.prototype, 'rm', { Object.defineProperty(String.prototype, 'rm', {
value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); } value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); }
}); });
@ -223,37 +226,38 @@ globalThis.global = globalThis;
var use_cache = {}; var use_cache = {};
globalThis.use = function use(file, env = {}, script) { globalThis.use = function use(file) {
file = Resources.find_script(file); file = Resources.find_script(file);
profile.cache("USE", file); profile.cache("USE", file);
if (use_cache[file]) { if (use_cache[file]) {
var ret = use_cache[file].call(env); var ret = use_cache[file]();
return; profile.endcache(" [cached]");
return ret;
} }
script ??= Resources.replstrs(file);
var script = Resources.replstrs(file);
script = `(function() { var self = this; ${script}; })`; script = `(function() { var self = this; ${script}; })`;
var fn = os.eval(file, script); var fn = os.eval(file, script);
use_cache[file] = fn; use_cache[file] = fn;
var ret = fn.call(env); var ret = fn();
profile.endcache(); profile.endcache();
return ret; return ret;
} }
function stripped_use (file, env = {}, script) { function stripped_use (file, script) {
file = Resources.find_script(file); file = Resources.find_script(file);
if (use_cache[file]) { if (use_cache[file]) {
var ret = use_cache[file].call(env); var ret = use_cache[file]();
return; return ret;
} }
script ??= Resources.replstrs(file); script ??= Resources.replstrs(file);
script = `(function() { var self = this; ${script}; })`; script = `(function() { var self = this; ${script}; })`;
var fn = os.eval(file, script); var fn = os.eval(file, script);
var ret = fn.call(env); var ret = fn();
profile.endcache(); profile.endcache();
return ret; return ret;
@ -264,7 +268,7 @@ function bare_use(file)
var script = io.slurp(file); var script = io.slurp(file);
if (!script) return; if (!script) return;
script = `(function() { var self = this; ${script}; })`; script = `(function() { var self = this; ${script}; })`;
Object.assign(globalThis, os.eval(file, script).call(globalThis)); Object.assign(globalThis, os.eval(file, script)());
} }
globalThis.debug = {}; globalThis.debug = {};

View file

@ -146,16 +146,15 @@ var entity = {
}, },
spawn(text, config, callback) { spawn(text, config, callback) {
var ent = class_use(text, config, entity, function(ent) {
var ent = Object.create(entity); ent.transform = os.make_transform();
ent.transform = os.make_transform(); ent.guid = prosperon.guid();
ent.components = {};
ent.guid = prosperon.guid(); ent.objects = {};
ent.timers = {};
ent.components = {}; ent.ur = {};
ent.objects = {}; });
ent.timers = {}; /*
if (!text) if (!text)
ent.ur = emptyur; ent.ur = emptyur;
else if (text instanceof Object) {// assume it's an ur else if (text instanceof Object) {// assume it's an ur
@ -169,12 +168,6 @@ var entity = {
config = [ent.ur.data, config]; config = [ent.ur.data, config];
} }
if (typeof text === 'string')
use(text, ent);
else if (Array.isArray(text))
for (var path of text) use(path,ent);
profile.cache("ENTITY TIME", ent.ur.name);
var st = profile.now();
if (typeof config === 'string') if (typeof config === 'string')
Object.merge(ent, json.decode(Resources.replstrs(config))); Object.merge(ent, json.decode(Resources.replstrs(config)));
else if (Array.isArray(config)) else if (Array.isArray(config))
@ -187,6 +180,15 @@ var entity = {
Object.merge(ent,path); Object.merge(ent,path);
}; };
if (typeof text === 'string') {
class_use(
use(text, ent);
}
else if (Array.isArray(text))
for (var path of text) use(path,ent);
profile.cache("ENTITY TIME", ent.ur.name);
*/
ent.reparent(this); ent.reparent(this);
for (var [prop, p] of Object.entries(ent)) { for (var [prop, p] of Object.entries(ent)) {

View file

@ -76,7 +76,7 @@ var pre = function(data)
if (data.pos) cursor = data.pos.slice(); if (data.pos) cursor = data.pos.slice();
data.drawpos = cursor.slice().add(data.offset); data.drawpos = cursor.slice().add(data.offset);
if (data.opacity !== 1) { if (data.opacity && data.opacity !== 1) {
data.color = data.color.slice(); data.color = data.color.slice();
data.color[3] = data.opacity; data.color[3] = data.opacity;
} }

View file

@ -16,6 +16,7 @@ function calc_cpu(fn, times, diff=0)
function empty_fn() {} function empty_fn() {}
profile.cpu = function profile_cpu(fn, times = 1, q = "unnamed") { profile.cpu = function profile_cpu(fn, times = 1, q = "unnamed") {
var retgather = gathering_cpu;
profile.gather_stop(); profile.gather_stop();
var empty = calc_cpu(empty_fn, 100000); var empty = calc_cpu(empty_fn, 100000);
var mean = Math.mean(empty); var mean = Math.mean(empty);
@ -26,7 +27,10 @@ profile.cpu = function profile_cpu(fn, times = 1, q = "unnamed") {
var totalt = profile.best_t(elapsed); var totalt = profile.best_t(elapsed);
say(`profile [${q}]: ${avgt} ± ${profile.best_t(Math.ci(series))} [${totalt} for ${times} loops]`); say(`profile [${q}]: ${avgt} ± ${profile.best_t(Math.ci(series))} [${totalt} for ${times} loops]`);
start_prof_gather(); say(`result of function is ${fn()}`);
if (retgather)
profile.start_prof_gather();
} }
profile.ms = function(t) { return t/1000000; } profile.ms = function(t) { return t/1000000; }
@ -277,3 +281,25 @@ function printreport(cache, name) {
return report; return report;
}; };
profile.best_mem = function(bytes)
{
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Bytes';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return (bytes / Math.pow(1024, i)).toPrecision(3) + ' ' + sizes[i];
}
profile.print_mem = function()
{
var mem = os.mem();
say('total memory used: ' + profile.best_mem(mem.memory_used_size));
delete mem.memory_used_size;
delete mem.malloc_size;
for (var i in mem) {
if (i.includes("size"))
say(" " + i + " :: " + profile.best_mem(mem[i]));
}
}
return {profile};

View file

@ -920,10 +920,13 @@ prosperon.render = function()
render.end_pass(); render.end_pass();
profile.endframe(); profile.endframe();
profile.endframe();
profile.frame("post process"); profile.endframe();
/* draw the image of the game world first */ /* draw the image of the game world first */
render.glue_pass(); render.glue_pass();
profile.frame("frame");
profile.frame("render");
profile.frame("post process");
render.viewport(...prosperon.camera.view()); render.viewport(...prosperon.camera.view());
render.use_shader(render.postshader); render.use_shader(render.postshader);
render.use_mat({diffuse:prosperon.screencolor}); render.use_mat({diffuse:prosperon.screencolor});
@ -1002,6 +1005,4 @@ prosperon.process = function process() {
profile.endframe(); profile.endframe();
} }
return {render}; return {render};

View file

@ -15,9 +15,11 @@ if (os.sys() === 'macos') {
} }
//appy.inputs.f12 = function() { mum.debug = !mum.debug; } //appy.inputs.f12 = function() { mum.debug = !mum.debug; }
appy.inputs.f12 = function() { profile.cpu_frame(); }
appy.inputs.f11 = window.toggle_fullscreen; appy.inputs.f9 = function() { profile.print_mem(); }
appy.inputs.f10 = function() { profile.toggle_frame_avg(); } appy.inputs.f10 = function() { profile.toggle_frame_avg(); }
appy.inputs.f11 = window.toggle_fullscreen;
appy.inputs.f12 = function() { profile.cpu_frame(); }
appy.inputs['M-f4'] = prosperon.quit; appy.inputs['M-f4'] = prosperon.quit;
player[0].control(appy); player[0].control(appy);
@ -240,7 +242,7 @@ Cmdline.register_order("play", function(argv) {
if (argv[0]) if (argv[0])
io.chdir(argv[0]); io.chdir(argv[0]);
game.loadurs(); // game.loadurs();
if (!io.exists(projectfile)) { if (!io.exists(projectfile)) {
say("No game to play. Try making one with 'prosperon init'."); say("No game to play. Try making one with 'prosperon init'.");
@ -320,7 +322,7 @@ Cmdline.register_order("about", function(argv) {
}, "Get information about this game."); }, "Get information about this game.");
Cmdline.register_order("ur", function(argv) { Cmdline.register_order("ur", function(argv) {
game.loadurs(); // game.loadurs();
for (var i of ur._list.sort()) say(i); for (var i of ur._list.sort()) say(i);
}, "Get information about the ur types in your game."); }, "Get information about the ur types in your game.");

View file

@ -33,6 +33,7 @@
#include "par/par_shapes.h" #include "par/par_shapes.h"
#include "sokol_glue.h" #include "sokol_glue.h"
#include <chipmunk/chipmunk_unsafe.h> #include <chipmunk/chipmunk_unsafe.h>
#include <chipmunk/chipmunk_structs.h>
#include "gui.h" #include "gui.h"
#include "timer.h" #include "timer.h"
@ -1315,6 +1316,21 @@ JSC_CCALL(vector_angledist,
return number2js(dist); return number2js(dist);
) )
JSC_CCALL(vector_length,
int len = js_arrlen(argv[0]);
switch(len) {
case 2: return number2js(HMM_LenV2(js2vec2(argv[0])));
case 3: return number2js(HMM_LenV3(js2vec3(argv[0])));
case 4: return number2js(HMM_LenV4(js2vec4(argv[0])));
}
double sum = 0;
for (int i = 0; i < len; i++)
sum += pow(js2number(js_getpropidx(argv[0], i)), 2);
return number2js(sqrt(sum));
)
double r2() double r2()
{ {
return (double)rand() / (double)RAND_MAX ; return (double)rand() / (double)RAND_MAX ;
@ -1415,7 +1431,8 @@ static const JSCFunctionListEntry js_vector_funcs[] = {
MIST_FUNC_DEF(vector, mean, 1), MIST_FUNC_DEF(vector, mean, 1),
MIST_FUNC_DEF(vector, sum, 1), MIST_FUNC_DEF(vector, sum, 1),
MIST_FUNC_DEF(vector, sigma, 1), MIST_FUNC_DEF(vector, sigma, 1),
MIST_FUNC_DEF(vector, median, 1) MIST_FUNC_DEF(vector, median, 1),
MIST_FUNC_DEF(vector, length, 1)
}; };
#define JS_HMM_FN(OP, HMM, SIGN) \ #define JS_HMM_FN(OP, HMM, SIGN) \
@ -2501,6 +2518,46 @@ JSC_CCALL(os_quit, quit();)
JSC_CCALL(os_exit, exit(js2number(argv[0]));) JSC_CCALL(os_exit, exit(js2number(argv[0]));)
JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space)); JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space));
JSC_CCALL(os_gc, script_gc()); JSC_CCALL(os_gc, script_gc());
JSC_CCALL(os_mem_limit, script_mem_limit(js2number(argv[0])))
JSC_CCALL(os_gc_threshold, script_gc_threshold(js2number(argv[0])))
JSC_CCALL(os_max_stacksize, script_max_stacksize(js2number(argv[0])))
#define JSOBJ_ADD_FIELD(OBJ, STRUCT, FIELD, TYPE) \
js_setpropstr(OBJ, #FIELD, TYPE##2js(STRUCT.FIELD));\
#define JSJMEMRET(FIELD) JSOBJ_ADD_FIELD(ret, jsmem, FIELD, number)
JSC_CCALL(os_mem,
JSMemoryUsage jsmem;
JS_ComputeMemoryUsage(rt, &jsmem);
ret = JS_NewObject(js);
JSJMEMRET(malloc_size)
JSJMEMRET(malloc_limit)
JSJMEMRET(memory_used_size)
JSJMEMRET(memory_used_count)
JSJMEMRET(atom_count)
JSJMEMRET(atom_size)
JSJMEMRET(str_count)
JSJMEMRET(str_size)
JSJMEMRET(obj_count)
JSJMEMRET(obj_size)
JSJMEMRET(prop_count)
JSJMEMRET(prop_size)
JSJMEMRET(shape_count)
JSJMEMRET(shape_size)
JSJMEMRET(js_func_count)
JSJMEMRET(js_func_size)
JSJMEMRET(js_func_code_size)
JSJMEMRET(js_func_pc2line_count)
JSJMEMRET(js_func_pc2line_size)
JSJMEMRET(c_func_count)
JSJMEMRET(array_count)
JSJMEMRET(fast_array_count)
JSJMEMRET(fast_array_elements)
JSJMEMRET(binary_object_count)
JSJMEMRET(binary_object_size)
)
JSC_SSCALL(os_eval, ret = script_eval(str, str2)) JSC_SSCALL(os_eval, ret = script_eval(str, str2))
JSC_CCALL(os_make_body, JSC_CCALL(os_make_body,
@ -2618,6 +2675,13 @@ JSC_CCALL(os_make_circle2d,
return ret; return ret;
) )
JSC_CCALL(os_make_timer, return timer2js(timer_make()))
JSC_CCALL(os_update_timers, timer_update(js2number(argv[0])))
JSC_CCALL(os_obj_size,
)
JSC_CCALL(poly2d_setverts, JSC_CCALL(poly2d_setverts,
cpShape *s = js2cpShape(self); cpShape *s = js2cpShape(self);
HMM_Vec2 *v = js2cpvec2arr(argv[0]); HMM_Vec2 *v = js2cpvec2arr(argv[0]);
@ -2938,6 +3002,12 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_hemisphere, 2), MIST_FUNC_DEF(os, make_hemisphere, 2),
MIST_FUNC_DEF(os, make_plane, 2), MIST_FUNC_DEF(os, make_plane, 2),
MIST_FUNC_DEF(os, make_video, 1), MIST_FUNC_DEF(os, make_video, 1),
MIST_FUNC_DEF(os, make_timer, 0),
MIST_FUNC_DEF(os, update_timers, 1),
MIST_FUNC_DEF(os, mem, 1),
MIST_FUNC_DEF(os, mem_limit, 1),
MIST_FUNC_DEF(os, gc_threshold, 1),
MIST_FUNC_DEF(os, max_stacksize, 1)
}; };
#include "steam.h" #include "steam.h"

View file

@ -110,6 +110,7 @@ JSValue TYPE##2js(TYPE *n) { \
return j; }\ return j; }\
\ \
static JSValue js_##TYPE##_memid (JSContext *js, JSValue self) { return str2js("%p", js2##TYPE(self)); } \ static JSValue js_##TYPE##_memid (JSContext *js, JSValue self) { return str2js("%p", js2##TYPE(self)); } \
static JSValue js_##TYPE##_memsize (JSContext *js, JSValue self) { return number2js(sizeof(TYPE)); } \
#define QJSGLOBALCLASS(NAME) \ #define QJSGLOBALCLASS(NAME) \
JSValue NAME = JS_NewObject(js); \ JSValue NAME = JS_NewObject(js); \
@ -126,6 +127,7 @@ QJSCLASSPREP(TYPE); \
JSValue TYPE##_proto = JS_NewObject(js); \ JSValue TYPE##_proto = JS_NewObject(js); \
JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \
JS_SetPropertyStr(js, TYPE##_proto, "memid", JS_NewCFunction(js, &js_##TYPE##_memid, "memid", 0)); \ JS_SetPropertyStr(js, TYPE##_proto, "memid", JS_NewCFunction(js, &js_##TYPE##_memid, "memid", 0)); \
JS_SetPropertyStr(js, TYPE##_proto, "memsize", JS_NewCFunction(js, &js_##TYPE##_memsize, "memsize", 0)); \
JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \
#define countof(x) (sizeof(x)/sizeof((x)[0])) #define countof(x) (sizeof(x)/sizeof((x)[0]))

View file

@ -16,6 +16,9 @@ JSRuntime *rt = NULL;
#define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP #define JS_EVAL_FLAGS JS_EVAL_FLAG_STRICT | JS_EVAL_FLAG_STRIP
#endif #endif
static JSValue start_gc;
static JSValue end_gc;
void script_startup() { void script_startup() {
rt = JS_NewRuntime(); rt = JS_NewRuntime();
js = JS_NewContext(rt); js = JS_NewContext(rt);
@ -44,6 +47,9 @@ return;
} }
void script_gc() { JS_RunGC(rt); } void script_gc() { JS_RunGC(rt); }
void script_mem_limit(size_t limit) { JS_SetMemoryLimit(rt, limit); }
void script_gc_threshold(size_t threshold) { JS_SetGCThreshold(rt, threshold); }
void script_max_stacksize(size_t size) { JS_SetMaxStackSize(rt, size); }
void js_stacktrace() { void js_stacktrace() {
if (!js) return; if (!js) return;
@ -52,6 +58,7 @@ void js_stacktrace() {
#endif #endif
} }
void script_evalf(const char *format, ...) void script_evalf(const char *format, ...)
{ {
JSValue obj; JSValue obj;

View file

@ -30,6 +30,9 @@ JSValue script_eval(const char *file, const char *script);
void script_call_sym(JSValue sym, int argc, JSValue *argv); void script_call_sym(JSValue sym, int argc, JSValue *argv);
void script_gc(); void script_gc();
void script_mem_limit(size_t limit);
void script_gc_threshold(size_t threshold);
void script_max_stacksize(size_t size);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -32,6 +32,7 @@
#include <time.h> #include <time.h>
#include <fenv.h> #include <fenv.h>
#include <math.h> #include <math.h>
#include <script.h>
#if defined(__APPLE__) #if defined(__APPLE__)
#include <malloc/malloc.h> #include <malloc/malloc.h>
#elif defined(__linux__) || defined(__GLIBC__) #elif defined(__linux__) || defined(__GLIBC__)
@ -112,6 +113,22 @@ void quickjs_set_dumpout(FILE *f)
//#define DUMP_PROMISE //#define DUMP_PROMISE
//#define DUMP_READ_OBJECT //#define DUMP_READ_OBJECT
#ifdef DUMP
//#define DUMP_FREE
//#define DUMP_MEM
//#define DUMP_CLOSURE
#define DUMP_GC
//#define DUMP_GC_FREE
#define DUMP_LEAKS 1
//#define DUMP_OBJECTS
#define DUMP_CLOSURE
//#define DUMP_OBJECTS
//#define DUMP_ATOMS
//#define DUMP_SHAPES
//#define DUMP_MODULE_RESOLVE
//#define DUMP_PROMISE
#endif
/* test the GC by forcing it before each object allocation */ /* test the GC by forcing it before each object allocation */
//#define FORCE_GC_AT_MALLOC //#define FORCE_GC_AT_MALLOC

View file

@ -1,22 +1,33 @@
#include "timer.h" #include "timer.h"
#include <stdio.h>
#include "stb_ds.h" #include "stb_ds.h"
timer *timers; timer **timers;
timer *timer_make() timer *timer_make()
{ {
return NULL; timer *t = calloc(sizeof(*t),1);
arrput(timers, t);
return t;
} }
void timer_free(timer *t) void timer_free(timer *t)
{ {
printf("before free arrlen if timers is now %d\n", arrlen(timers));
for (int i = 0; i < arrlen(timers); i++) {
if (timers[i] == t) {
arrdelswap(timers,i);
break;
}
}
free(t);
printf("arrlen if timers is now %d\n", arrlen(timers));
} }
void timer_update(double dt) void timer_update(double dt)
{ {
for (int i = 0; i < arrlen(timers); i++) { for (int i = 0; i < arrlen(timers); i++) {
timers[i].remain -= dt; timers[i]->remain -= dt;
} }
} }

View file

@ -5,7 +5,6 @@ typedef struct timer {
double remain; double remain;
} timer; } timer;
timer *timer_make(); timer *timer_make();
void timer_free(timer *t); void timer_free(timer *t);
void timer_update(double dt); void timer_update(double dt);