Optimize Material() when pngParameters ~= nil#2444
Optimize Material() when pngParameters ~= nil#2444GrayWolf64 wants to merge 2 commits intoFacepunch:masterfrom
Material() when pngParameters ~= nil#2444Conversation
* Set `string.find()` no_patterns to true, possibly allowing luajit to compile this more efficiently * Eliminate small string creations resulting from `..`
Material()Material() when pngParameters ~= nil
local SysTime = SysTime
local ipairs = ipairs
local MsgC = MsgC
function GMODBenchmark(repeats, ...)
local times = {}
for i=1,5 do print() end
for i = 1, 2 do
if i == 1 then
MsgC(Color(250, 129, 95), "[Benchmark] ", Color(35, 153, 189), "Loop 1: JIT Off\n")
else
MsgC(Color(250, 129, 95), "[Benchmark] ", Color(35, 153, 189), "Loop 2: JIT On\n")
end
for k, benchmark_function in ipairs({...}) do
if i == 1 then
jit.off()
jit.flush()
else
jit.on()
end
local start_time = SysTime()
for i = 1, repeats do
benchmark_function()
end
local end_time = SysTime()
times[k] = end_time - start_time
MsgC(Color(250, 129, 95), "[Benchmark] ", Color(35, 153, 189), "Function ", Color(255, 255, 255), k, Color(35, 153, 189), ": ", Color(255, 255, 255), string.format("%.6f", times[k]), " seconds\n")
end
end
end
local mat_flags = { 0, 0, 0, 0, 0, 0, 0 }
local C_Material = Material
local function Material( name, words )
if ( !words ) then return C_Material( name ) end
mat_flags[ 1 ] = string.find( words, "vertexlitgeneric", 1, true ) and 1 or 0
mat_flags[ 2 ] = string.find( words, "nocull", 1, true ) and 1 or 0
mat_flags[ 3 ] = string.find( words, "alphatest", 1, true ) and 1 or 0
mat_flags[ 4 ] = string.find( words, "mips", 1, true ) and 1 or 0
mat_flags[ 5 ] = string.find( words, "noclamp", 1, true ) and 1 or 0
mat_flags[ 6 ] = string.find( words, "smooth", 1, true ) and 1 or 0
mat_flags[ 7 ] = string.find( words, "ignorez", 1, true ) and 1 or 0
return C_Material( name, table.concat( mat_flags, "" ) )
end
local function OldMaterial( name, words )
if ( !words ) then return C_Material( name ) end
local str = (words:find("vertexlitgeneric") and "1" or "0")
str = str .. (words:find("nocull") and "1" or "0")
str = str .. (words:find("alphatest") and "1" or "0")
str = str .. (words:find("mips") and "1" or "0")
str = str .. (words:find("noclamp") and "1" or "0")
str = str .. (words:find("smooth") and "1" or "0")
str = str .. (words:find("ignorez") and "1" or "0")
return C_Material( name, str )
end
GMODBenchmark(10000,
function()
local mat = Material("models/debug/debugwhite", "vertexlitgeneric nocull alphatest mips noclamp smooth ignorez")
end,
function()
local mat = OldMaterial("models/debug/debugwhite", "vertexlitgeneric nocull alphatest mips noclamp smooth ignorez")
end) |
|
You can make inline concat here, it'll be faster than the original separate concat and your table concat. https://gitspartv.github.io/LuaJIT-Benchmarks/#test18. To directly call string.find is a good idea. My testing
Code-- https://github.com/noaccessl/gluafuncbudget
gluafuncbudget.Configure( {
usercpu = 'i7-3770 @ 3.40GHz';
frames = 50;
iterations_per_frame = 25;
} )
local C_Material = select( 2, debug.getupvalue( Material, 1 ) )
local function g_pre() return 'models/debug/debugwhite', "vertexlitgeneric nocull alphatest mips noclamp smooth ignorez" end
gluafuncbudget.Queue( {
name = "Material: GMod Variant";
pre = g_pre;
main = function( name, words )
local str = (words:find("vertexlitgeneric") and "1" or "0")
str = str .. (words:find("nocull") and "1" or "0")
str = str .. (words:find("alphatest") and "1" or "0")
str = str .. (words:find("mips") and "1" or "0")
str = str .. (words:find("noclamp") and "1" or "0")
str = str .. (words:find("smooth") and "1" or "0")
str = str .. (words:find("ignorez") and "1" or "0")
C_Material( name, str )
end
} )
local mat_flags = { 0, 0, 0, 0, 0, 0, 0 }
gluafuncbudget.Queue( {
name = "Material: GrayWolf64's";
pre = g_pre;
main = function( name, words )
mat_flags[ 1 ] = string.find( words, "vertexlitgeneric", 1, true ) and 1 or 0
mat_flags[ 2 ] = string.find( words, "nocull", 1, true ) and 1 or 0
mat_flags[ 3 ] = string.find( words, "alphatest", 1, true ) and 1 or 0
mat_flags[ 4 ] = string.find( words, "mips", 1, true ) and 1 or 0
mat_flags[ 5 ] = string.find( words, "noclamp", 1, true ) and 1 or 0
mat_flags[ 6 ] = string.find( words, "smooth", 1, true ) and 1 or 0
mat_flags[ 7 ] = string.find( words, "ignorez", 1, true ) and 1 or 0
C_Material( name, table.concat( mat_flags, "" ) )
end
} )
gluafuncbudget.Queue( {
name = "Material: GMod Variant; inline concat";
pre = g_pre;
main = function( name, words )
local str = (words:find("vertexlitgeneric") and "1" or "0")
.. (words:find("nocull") and "1" or "0")
.. (words:find("alphatest") and "1" or "0")
.. (words:find("mips") and "1" or "0")
.. (words:find("noclamp") and "1" or "0")
.. (words:find("smooth") and "1" or "0")
.. (words:find("ignorez") and "1" or "0")
C_Material( name, str )
end
} )
gluafuncbudget.Queue( {
name = "Material: GMod Variant; inline concat + direct string.find";
pre = g_pre;
main = function( name, words )
local str = (string.find(words, "vertexlitgeneric") and "1" or "0")
.. (string.find(words, "nocull") and "1" or "0")
.. (string.find(words, "alphatest") and "1" or "0")
.. (string.find(words, "mips") and "1" or "0")
.. (string.find(words, "noclamp") and "1" or "0")
.. (string.find(words, "smooth") and "1" or "0")
.. (string.find(words, "ignorez") and "1" or "0")
C_Material( name, str )
end
} ) |
|
You should've done something like local C_Material = select( 2, debug.getupvalue( Material, 1 ) )instead of just local C_Material = MaterialAren't you getting the gmod's lua function? |
|
@noaccessl Does I'm also curious if the following one is the most performant: --
-- Send C the flags for any materials we want to create
--
local mat_flags = {}
for a=0,1 do -- 128 different flags in total lol
mat_flags[a] = {}
for b=0,1 do
mat_flags[a][b] = {}
for c=0,1 do
mat_flags[a][b][c] = {}
for d=0,1 do
mat_flags[a][b][c][d] = {}
for e=0,1 do
mat_flags[a][b][c][d][e] = {}
for f=0,1 do
mat_flags[a][b][c][d][e][f] = {}
for g=0,1 do
mat_flags[a][b][c][d][e][f][g] = string.format("%d%d%d%d%d%d%d", a, b, c, d, e, f, g)
end
end
end
end
end
end
end
local C_Material = Material
function Material( name, words )
if ( !words ) then return C_Material( name ) end
return C_Material( name, mat_flags[string.find( words, "vertexlitgeneric", 1, true ) and 1 or 0]
[string.find( words, "nocull", 1, true ) and 1 or 0]
[string.find( words, "alphatest", 1, true ) and 1 or 0]
[string.find( words, "mips", 1, true ) and 1 or 0]
[string.find( words, "noclamp", 1, true ) and 1 or 0]
[string.find( words, "smooth", 1, true ) and 1 or 0]
[string.find( words, "ignorez", 1, true ) and 1 or 0])
endThis is over optimization I think and the setup code looks quite ugly. And I don't know if my optimization is really necessary because on the wiki page the |
|
Looks bulky. Plus it preoccupies some memory. But ultimately, you're trying to optimize the "flags construction" part. And we have to remember, it still comes down to calling Codegluafuncbudget.Configure( {
usercpu = 'Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz';
frames = 50;
iterations_per_frame = 1e4;
measure_unit --[[= 'ms']];
digit --[[= 5]];
comparison_basis --[[= 'average']];
shown_metrics --[[= 'median min max average stddev avgfps']];
-- jit_off_all = true
} )
local string_find = string.find
local function fnGetWords()
return "vertexlitgeneric nocull alphatest mips noclamp smooth ignorez"
end
gluafuncbudget.Queue( {
name = "Flags Construction: GMod's";
standard = true;
pre = fnGetWords;
main = function( words )
local str = ( words:find( 'vertexlitgeneric' ) and '1' or '0' )
str = str .. ( words:find( 'nocull' ) and '1' or '0' )
str = str .. ( words:find( 'alphatest' ) and '1' or '0' )
str = str .. ( words:find( 'mips' ) and '1' or '0' )
str = str .. ( words:find( 'noclamp' ) and '1' or '0' )
str = str .. ( words:find( 'smooth' ) and '1' or '0' )
str = str .. ( words:find( 'ignorez' ) and '1' or '0' )
end
} )
gluafuncbudget.Queue( {
name = "Flags Construction: GMod's + direct string.find";
pre = fnGetWords;
main = function( words )
local str = ( string_find( words, 'vertexlitgeneric', 1, true ) and '1' or '0' )
str = str .. ( string_find( words, 'nocull', 1, true ) and '1' or '0' )
str = str .. ( string_find( words, 'alphatest', 1, true ) and '1' or '0' )
str = str .. ( string_find( words, 'mips', 1, true ) and '1' or '0' )
str = str .. ( string_find( words, 'noclamp', 1, true ) and '1' or '0' )
str = str .. ( string_find( words, 'smooth', 1, true ) and '1' or '0' )
str = str .. ( string_find( words, 'ignorez', 1, true ) and '1' or '0' )
end
} )
gluafuncbudget.Queue( {
name = "Flags Construction: GMod's + direct string.find + inline concat";
pre = fnGetWords;
main = function( words )
local str = ( string_find( words, 'vertexlitgeneric', 1, true ) and '1' or '0' )
.. ( string_find( words, 'nocull', 1, true ) and '1' or '0' )
.. ( string_find( words, 'alphatest', 1, true ) and '1' or '0' )
.. ( string_find( words, 'mips', 1, true ) and '1' or '0' )
.. ( string_find( words, 'noclamp', 1, true ) and '1' or '0' )
.. ( string_find( words, 'smooth', 1, true ) and '1' or '0' )
.. ( string_find( words, 'ignorez', 1, true ) and '1' or '0' )
end
} )
local _mat_flags = { 0, 0, 0, 0, 0, 0, 0 }
local table_concat = table.concat
gluafuncbudget.Queue( {
name = "Flags Construction: table concat";
pre = fnGetWords;
main = function( words )
_mat_flags[1] = string_find( words, 'vertexlitgeneric', 1, true ) and 1 or 0
_mat_flags[2] = string_find( words, 'nocull', 1, true ) and 1 or 0
_mat_flags[3] = string_find( words, 'alphatest', 1, true ) and 1 or 0
_mat_flags[4] = string_find( words, 'mips', 1, true ) and 1 or 0
_mat_flags[5] = string_find( words, 'noclamp', 1, true ) and 1 or 0
_mat_flags[6] = string_find( words, 'smooth', 1, true ) and 1 or 0
_mat_flags[7] = string_find( words, 'ignorez', 1, true ) and 1 or 0
table_concat( _mat_flags, '' )
end
} )
local mat_flags = {}
for a = 0,1 do
mat_flags[a] = {}
for b = 0,1 do
mat_flags[a][b] = {}
for c = 0,1 do
mat_flags[a][b][c] = {}
for d = 0,1 do
mat_flags[a][b][c][d] = {}
for e = 0,1 do
mat_flags[a][b][c][d][e] = {}
for f = 0,1 do
mat_flags[a][b][c][d][e][f] = {}
for g = 0,1 do
mat_flags[a][b][c][d][e][f][g] = string.format( '%d%d%d%d%d%d%d', a, b, c, d, e, f, g )
end
end
end
end
end
end
end
gluafuncbudget.Queue( {
name = "Flags Construction: Manifold Lookup";
pre = fnGetWords;
main = function( words )
local str = mat_flags[string_find( words, 'vertexlitgeneric', 1, true ) and 1 or 0]
[string_find( words, 'nocull', 1, true ) and 1 or 0]
[string_find( words, 'alphatest', 1, true ) and 1 or 0]
[string_find( words, 'mips', 1, true ) and 1 or 0]
[string_find( words, 'noclamp', 1, true ) and 1 or 0]
[string_find( words, 'smooth', 1, true ) and 1 or 0]
[string_find( words, 'ignorez', 1, true ) and 1 or 0]
end
} ) |



string.find()no_patterns to true, possibly allowing luajit to compile this more efficiently..