maxscript has not very good loop iteration performance and you’re bound to use high level abstractions, so on large polycounts mxs will lose to python for sure. For python you can try MaxPlus or whatever came as a replacement in newer max versions to improve timings. But you’ll have to use c++ sdk sources to learn how it all works under the hood. Which can be overwhelming
In general x10 speedup can be achieved depending on the task if you switch to low level implementation with c++ or c#.
Align UV script optimizations
you can rewrite it so that you don’t have to make a separate mesh snapshot for each uv-element. If you have lots of elements it should definitely improve timings
...
fn getMapElementBBox3 node tverts channel:1 = if iskindof node Editable_Poly or iskindof node.baseobject Editable_Poly do
(
if polyop.getmapsupport node channel do
(
mesh = snapshotasmesh node
here’s what I suggested doing with uv-mesh representation
don’t know why but subsequent execution of this code doing twice as fast than the first run after max start
t1=timestamp();hf = heapfree
max create mode
with redraw off
(
-- example scene
sp =
(
max create mode
delete objects
sp = teapot name:"test_mesh" mapcoords:on isSelected:true
addmodifier sp (Uvwmap maptype:0)
sp = converttopoly sp
for k=1 to 3 do polyop.attach sp (copy sp)
update sp
sp
)
fn GetAllMeshElements node =
(
local tmesh = snapshotasmesh node
local faces = #{1..tmesh.numfaces}
local verts = for v = 1 to tmesh.numverts collect #()
local undone = #{1..tmesh.numverts}
local elements = #()
for j in faces do
(
f = getface tmesh j
append verts[f[1]] j
append verts[f[2]] j
append verts[f[3]] j
)
for i in faces do
(
element = #(i)
for j in element where faces[j] do
(
faces[j] = false
f = getface tmesh j
if undone[f[1]] do (join element verts[f[1]]; undone[f[1]] = false )
if undone[f[2]] do (join element verts[f[2]]; undone[f[2]] = false )
if undone[f[3]] do (join element verts[f[3]]; undone[f[3]] = false )
)
append elements (element as bitarray)
)
elements
)
sel = selection[1]
convertToMesh sel
tri = snapshotasmesh sel
meshUV = mesh mesh:tri
channelInfo.CopyChannel meshUV 3 1
channelInfo.PasteChannel meshUV 1 0
collapseStack meshUV
elems = GetAllMeshElements meshUV
meshop_getVertsUsingFace = meshop.getVertsUsingFace
vts = #()
vts.count = tri.numverts
for el in elems do
(
fv = meshop_getVertsUsingFace meshUV el
shift = [ 1e9, 1e9, 0 ]
for v in fv do
(
vts[v] = vv = getVert meshUV v
if vv.x < shift.x do shift.x = vv.x
if vv.y < shift.y do shift.y = vv.y
)
for v in fv do setvert meshUV v (vts[v] - shift)
)
update meshUV
channelInfo.CopyChannel meshUV 1 0
channelInfo.PasteChannel sel 3 1
delete meshUV
free tri
)
format "Time: %sec. Mem: %\n" ((timestamp()-t1)/1000 as float) (hf-heapfree)
Could you post an example of the scene you usually work with? (preferably MAX 2020 version). I need to see the type of data you have. How best to optimize depends on it.
It’s easy not to use a snapshot for a mesh, as well as any conversion to mesh geometry at all. I do this in order to use the methods of meshop mapfaces to elements that are not part of polyop.
I assume that after improving the code and algorithms, we can increase the performance up to 4 times continuing to use only pure maxscript.
Here is an example file.
Katwijk.max (25.9 MB)
You can ignore the roofs, only the walls are relevant.
@Serejah I did a quick test and it seems fast, but I’m not sure how fast. I only tried a small portion of the example file. It was faster than my original script anyway.
I did a test in Blender, which is the source app for the buildings, and it did it in about 4 min 45 sec. I first clicked left, and then bottom. Maybe it could do it twice as fast if there was a button for bottom left align, but there’s not.
I’ve made the test - do all using c++ :
roofs :
CPP SDK elements:22610 time:205
walls:
CPP SDK elements:137464 time:4315
the time in msec…
it definitely beats the Blender
Very nice 
I guess I will have to learn a bit more to progress further 
@denisT What’s your opinion on python in Max?
Most likely your number is more correct. I just copy pasted uvs to mesh and used MNMeshElements to check the count. And maybe it isn’t a valid method at all.
I think that is possible to make pure MXS version which can do the job for about 40-60 sec
Serejah,
do you remember that MXS algorithm to find all mesh geom elements? You already found it once on this forum…
I posted above my updated version of Jorge’s code. If I remember correctly it was working bit faster, but I didn’t do muchs tests to see if it doesn;t break on some corner case scenarios
Thanks! 
I will try to make this UV shift thing based on fast element search using only MXS… the same I do in my cpp code
and finally:
fn shiftPolyMapAllElements node ch:1 =
(
local faces = #{1..node.numfaces}
local numtverts = polyop.getnummapverts node ch
local verts = for v = 1 to numtverts collect #()
local undone = #{1..numtverts}
local elements = #()
getmapface = polyop.getmapface
getmapvert = polyop.getmapvert
setmapvert = polyop.setmapvert
for f in faces do
(
tvv = getmapface node ch f
for tv in tvv do append verts[tv] f
)
for i in faces do
(
element = #(i)
tverts = #()
for j in element where faces[j] do
(
faces[j] = off
f = getmapface node ch j
for k=1 to f.count do
(
v = f[k]
if undone[v] do
(
join element verts[v]
append tverts v
undone[v] = off
)
)
)
u = 1e9
v = 1e9
pp = for tv in tverts collect
(
p = getmapvert node ch tv
if p.x < u do u = p.x
if p.y < v do v = p.y
p
)
shift = [u,v,0]
k = 1
--format ">> % = %\n" tverts.count tverts
for tv in tverts do
(
setmapvert node ch tv (pp[k] - shift)
k += 1
)
append elements tverts.count
)
update node
elements
)
undo "Shift POLY Elements" on
(
gc()
node = $
converttopoly node -- for undo!!!
t1 = timestamp()
m1 = heapfree
elements = shiftPolyMapAllElements node
format "MXS POLY elements:% time:% memory:% >> %\n" (try(elements.count) catch(-1)) (timestamp() - t1) (m1 - heapfree) elements
)
WALLS:
MXS POLY elements:137464 time:4237 memory:268027116L >> #(5, 4, 5, 4, 5, 4, 5, 4, 13, 12, 11, 12, 7, 4, 4, 8, 4, 19, 4, 4, …)
pure MXS is ~4 sec on my machine (!)
Blender sucks! 
Thank you for restoring my faith, oh wise one 
Seriously though, that’s pretty awesome 
I’ll try it out tomorrow!
Thanks for the help! I hope others find it useful too!
If anyone needs to bottom left align 100k+ UV islands, they will find this thread 