[Closed] MaxScript methods performance testing
Hi guys, I’d like to run some tests on common Editable Poly functions for the sake of speed and memory optimization. I wish to know if the test structure I coded seems up to the task for fair results, and more extensive tests. Any suggestion is very welcome. Thanks.
struct PerformanceTester
(
iStartMem = 0,
iStartTime = 0,
iStopMem = 0,
iStopTime = 0,
iCycle = 0,
iResTime = 0,
iResMem = 0,
function start =
(
gc()
iCycle += 1
iStartMem = (heapSize - heapFree)
iStartTime = timeStamp()
),
function stop =
(
iStopTime = timeStamp()
iStopMem = (heapSize - heapFree)
iResTime += ((iStopTime - iStartTime) / 1000.0)
iResMem += ((iStopMem - iStartMem) / 1024.0)
),
function report =
(
format "Average processing on % iteration(s) took:
" iCycle
format "% seconds
" (iResTime / iCycle)
format "% Kbytes
" (iResMem / iCycle)
iCycle = 0
iResTime = 0
iResMem = 0
)
)
Follows a test on one of most used polyOp methods: getVert()
-- polyOp.getVert TEST
(
local theWatch = PerformanceTester()
local gv = polyOp.getVert
local theSphere = convertToPoly(Sphere segments:200)
local iNumVerts = polyOp.getNumVerts theSphere
for i = 1 to 100 do
(
theWatch.start()
for j = 1 to iNumVerts do
(
polyOp.getVert theSphere j
)
theWatch.stop()
)
theWatch.report()
-- Average processing on 100 iteration(s) took:
-- 0.03749 seconds
-- 1272.57 Kbytes <-- memory leak?
for i = 1 to 100 do
(
theWatch.start()
for j = 1 to iNumVerts do
(
gv theSphere j
)
theWatch.stop()
)
theWatch.report()
-- Average processing on 100 iteration(s) took:
-- 0.02917 seconds <-- greater speed
-- 0.226563 Kbytes <-- lower memory consumption
delete theSphere
)
- Enrico
looks good to me man…only thing I would add maybe is a gc call in the stop method too – grab the memory pre-garbage collection & post-garbage collection to make sure the leak is collectable at least or if it causes errors.
Another thing I’ve noticed is leaks often cause an Unknown System Exception when garbage collecting, so this is a good way to make sure whatever code you’re running (not just poly ops) are not causing errors.
I’m going to use this to test the python system…thanks!
Hi Eric, thank you for the quick reply. I made some adjustments as you suggested, hoping it’s exactly what you meant. It seems polyOp.getVert() doesn’t lead to a memory leak, or at least it is collectible and doesn’t clutter the heap. I’m really glad this little structure could help you testing Python performances within 3ds Max. Thank you for the hard work!
struct PerformanceTester
(
iStartTime = 0,
iStartMem = 0,
iStopTime = 0,
iStopMem = 0,
iStopMemDelta = 0,
iCycle = 0,
iResTime = 0,
iResMem = 0,
iResMemDelta = 0,
function start =
(
gc()
iCycle += 1
iStartTime = timeStamp()
iStartMem = heapSize - heapFree
),
function stop =
(
iStopTime = timeStamp()
iResTime += (iStopTime - iStartTime) / 1000.0
iStopMem = heapSize - heapFree
iResMem += (iStopMem - iStartMem) / 1024.0
gc()
iStopMemDelta = heapSize - heapFree
iResMemDelta += (iStopMemDelta - iStartMem) / 1024.0
),
function report =
(
format "Average processing on % iteration(s) took:
" iCycle
format "% seconds
" (iResTime / iCycle)
format "% Kbytes used
" (iResMem / iCycle)
format "% Kbytes delta
" (iResMemDelta / iCycle)
iCycle = 0
iResTime = 0
iResMem = 0
iResMemClean = 0
)
)
-- polyOp.getVert TEST
(
theWatch = PerformanceTester()
local gv = polyOp.getVert
local theSphere = convertToPoly(Sphere segments:200)
local iNumVerts = polyOp.getNumVerts theSphere
for i = 1 to 100 do
(
theWatch.start()
for j = 1 to iNumVerts do
(
polyOp.getVert theSphere j
)
theWatch.stop()
)
theWatch.report()
-- Average processing on 100 iteration(s) took:
-- 0.04045 seconds
-- 1248.16 Kbytes used
-- -0.0508594 Kbytes delta
for i = 1 to 100 do
(
theWatch.start()
for j = 1 to iNumVerts do
(
gv theSphere j
)
theWatch.stop()
)
theWatch.report()
-- Average processing on 100 iteration(s) took:
-- 0.02873 seconds
-- 0.226563 Kbytes used
-- -0.103906 Kbytes delta
delete theSphere
)
- Enrico