Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Luau global import optimisation #1486

Merged
merged 3 commits into from
Apr 29, 2024

Conversation

ccuser44
Copy link
Contributor

Make compiler localize Luau globals if env is safe
For this to happen the parser has to know what globals are used and if env is safe so a pre-made lex tree must be used.

NOTE: Unfortunately uses a quick hack to add lex tokens in the lexer instead of having a parser function only add a local set expression containing the globals to the main chunk.

@Dimenpsyonal
Copy link
Member

I'm gonna be real, all these changes to code execution are probably going to backfire horribly

@PurpleCreativity
Copy link
Contributor

You Live only Once @Dimenpsyonal

@ccuser44
Copy link
Contributor Author

PoF:
image

Performance:
Loadstring no-localisation: 3.884305715560913 - 3.8650588989257812 - 3.9003798961639404
Loadstring localisation: 3.6001365184783936 - 3.589552879333496 - 3.555936813354492
Raw Luau: 0.07147550582885742 - 0.07510924339294434 - 0.06685996055603027

Perf script:

local primes = 
	{
		0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
		0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
		0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
		0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
		0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
		0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
		0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
		0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
		0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
		0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
		0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
		0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
		0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
		0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
		0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
		0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
	}

local function toHex(str)
	local result = str:gsub('.', function (char)
		return string.format("%02x", char:byte())
	end)

	return result
end

local function toBytes(value, length)
	local str = ""

	for i = 1, length do
		local rem = value % 256
		str = string.char(rem) .. str
		value = (value - rem) / 256
	end

	return str
end

local function readInt32(buffer, index)
	local value = 0

	for i = index, index + 3 do 
		value = (value * 256) + string.byte(buffer, i)
	end

	return value
end

local function digestBlock(msg, i, hash)
	local digest = {}

	for j = 1, 16 do 
		digest[j] = readInt32(msg, i + (j - 1) * 4) 
	end

	for j = 17, 64 do
		local v = digest[j - 15]
		local s0 = bit32.bxor(bit32.rrotate(v, 7), bit32.rrotate(v, 18), bit32.rshift(v, 3))

		v = digest[j - 2]
		digest[j] = digest[j - 16] + s0 + digest[j - 7] + bit32.bxor(bit32.rrotate(v, 17), bit32.rrotate(v, 19), bit32.rshift(v, 10))
	end

	local a, b, c, d, e, f, g, h = unpack(hash)

	for i = 1, 64 do
		local s0 = bit32.bxor(bit32.rrotate(a, 2), bit32.rrotate(a, 13), bit32.rrotate(a, 22))
		local maj = bit32.bxor(bit32.band(a, b), bit32.band(a, c), bit32.band(b, c))

		local t2 = s0 + maj
		local s1 = bit32.bxor(bit32.rrotate(e, 6), bit32.rrotate(e, 11), bit32.rrotate(e, 25))

		local ch = bit32.bxor(bit32.band(e, f), bit32.band(bit32.bnot(e), g))
		local t1 = h + s1 + ch + primes[i] + digest[i]

		h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
	end

	hash[1] = bit32.band(hash[1] + a)
	hash[2] = bit32.band(hash[2] + b)
	hash[3] = bit32.band(hash[3] + c)
	hash[4] = bit32.band(hash[4] + d)
	hash[5] = bit32.band(hash[5] + e)
	hash[6] = bit32.band(hash[6] + f)
	hash[7] = bit32.band(hash[7] + g)
	hash[8] = bit32.band(hash[8] + h)
end

local function sha256(msg)
	do
		local extra = 64 - ((#msg + 9) % 64)
		local len = toBytes(8 * #msg, 8)

		msg = msg .. '\128' .. string.rep('\0', extra) .. len
		assert(#msg % 64 == 0)
	end

	local hash = 
		{
			0x6a09e667,
			0xbb67ae85,
			0x3c6ef372,
			0xa54ff53a,
			0x510e527f,
			0x9b05688c,
			0x1f83d9ab,
			0x5be0cd19,	
		}

	for i = 1, #msg, 64 do 
		digestBlock(msg, i, hash)
	end

	local result = ""

	for i = 1, 8 do
		local value = hash[i]
		result = result .. toBytes(value, 4)
	end

	return toHex(result)
end

------------------------------------------------------------------

local input = string.rep(".", 26e4)

local now = tick()
local result = sha256(input)

print(tick() - now)
print(result)

------------------------------------------------------------------

@ccuser44
Copy link
Contributor Author

Unfortunately I just dont have the time to add the parser logic for the env replace so I had to use a hack for now because im very busy

@ccuser44
Copy link
Contributor Author

ccuser44 commented Apr 29, 2024

Before all optimizations (#1017 (affects), #1470 (affects), #1472, #1478 (affects), #1486 (affects)): 4.669577121734619 - 4.667480707168579 - 4.654944181442261

The getfenv removal + update + JIT + concat optimization + global localization shaved off about 1.5s. Ie. down from 4.7s to 3.5s

The last thing to add is full global localisation via parser logic + lexer set tagging:

  • Localize all library imports too to their own local variables
  • Compile const table.create to NEWTABLE with size set

@Dimenpsyonal Dimenpsyonal added the ✨ enhancement Enhancing or improving existing functionality label Apr 29, 2024
@Dimenpsyonal Dimenpsyonal merged commit 685adda into Epix-Incorporated:master Apr 29, 2024
2 checks passed
@ccuser44 ccuser44 deleted the patch-7 branch April 29, 2024 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ enhancement Enhancing or improving existing functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants