Đã có rất nhiều cách tiếp cận tốt trong các câu trả lời được cung cấp ( đây , đây và đây ). Nếu tốc độ là thứ bạn chủ yếu tìm kiếm, bạn chắc chắn nên cân nhắc thực hiện công việc thông qua API C của Lua, nhanh hơn nhiều lần so với mã Lua thô. Khi làm việc với các khối được tải trước (ví dụ: hàm tải ), sự khác biệt không lớn lắm nhưng vẫn đáng kể.
Đối với các giải pháp Lua thuần túy , hãy để tôi chia sẻ điểm chuẩn nhỏ này, tôi đã thực hiện. Nó bao gồm mọi câu trả lời được cung cấp cho đến ngày này và thêm một số tối ưu hóa. Tuy nhiên, điều cơ bản cần xem xét là:
Bạn sẽ cần lặp lại bao nhiêu lần các ký tự trong chuỗi?
- Nếu câu trả lời là "một lần", bạn nên tra cứu phần đầu tiên của dấu hiệu ("tốc độ thô").
- Nếu không, phần thứ hai sẽ cung cấp ước tính chính xác hơn, vì nó phân tích cú pháp chuỗi vào bảng, việc lặp lại nhanh hơn nhiều. Bạn cũng nên cân nhắc viết một hàm đơn giản cho việc này, như @Jarriz đã đề xuất.
Đây là mã đầy đủ:
local str = "Hello World!"
local attempts = 5000000
local reuses = 10
local x, c, elapsed, tbl
local stringbyte, stringchar, stringsub, stringgsub, stringgmatch = string.byte, string.char, string.sub, string.gsub, string.gmatch
print("-----------------------")
print("Raw speed:")
print("-----------------------")
x = os.clock()
for j = 1, attempts do
for i = 1, #str do
c = stringsub(str, i)
end
end
elapsed = os.clock() - x
print(string.format("V1: elapsed time: %.3f", elapsed))
x = os.clock()
for j = 1, attempts do
for c in stringgmatch(str, ".") do end
end
elapsed = os.clock() - x
print(string.format("V2: elapsed time: %.3f", elapsed))
x = os.clock()
for j = 1, attempts do
stringgsub(str, ".", function(c) end)
end
elapsed = os.clock() - x
print(string.format("V3: elapsed time: %.3f", elapsed))
local str2table = function(str)
local ret = {}
for i = 1, #str do
ret[i] = stringsub(str, i)
end
return ret
end
x = os.clock()
for j = 1, attempts do
tbl = str2table(str)
for i = 1, #tbl do
c = tbl[i]
end
end
elapsed = os.clock() - x
print(string.format("V4: elapsed time: %.3f", elapsed))
x = os.clock()
for j = 1, attempts do
tbl = {stringbyte(str, 1, #str)}
for i = 1, #tbl do
c = tbl[i]
end
end
elapsed = os.clock() - x
print(string.format("V5: elapsed time: %.3f", elapsed))
x = os.clock()
for j = 1, attempts do
tbl = {stringbyte(str, 1, #str)}
for i = 1, #tbl do
c = stringchar(tbl[i])
end
end
elapsed = os.clock() - x
print(string.format("V5b: elapsed time: %.3f", elapsed))
print("-----------------------")
print("Creating cache table ("..reuses.." reuses):")
print("-----------------------")
x = os.clock()
for k = 1, attempts do
tbl = {}
for i = 1, #str do
tbl[i] = stringsub(str, i)
end
for j = 1, reuses do
for i = 1, #tbl do
c = tbl[i]
end
end
end
elapsed = os.clock() - x
print(string.format("V1: elapsed time: %.3f", elapsed))
x = os.clock()
for k = 1, attempts do
tbl = {}
local tblc = 1
for c in stringgmatch(str, ".") do
tbl[tblc] = c
tblc = tblc + 1
end
for j = 1, reuses do
for i = 1, #tbl do
c = tbl[i]
end
end
end
elapsed = os.clock() - x
print(string.format("V2: elapsed time: %.3f", elapsed))
x = os.clock()
for k = 1, attempts do
tbl = {}
local tblc = 1
stringgsub(str, ".", function(c)
tbl[tblc] = c
tblc = tblc + 1
end)
for j = 1, reuses do
for i = 1, #tbl do
c = tbl[i]
end
end
end
elapsed = os.clock() - x
print(string.format("V3: elapsed time: %.3f", elapsed))
x = os.clock()
for k = 1, attempts do
tbl = str2table(str)
for j = 1, reuses do
for i = 1, #tbl do
c = tbl[i]
end
end
end
elapsed = os.clock() - x
print(string.format("V4: elapsed time: %.3f", elapsed))
x = os.clock()
for k = 1, attempts do
tbl = {stringbyte(str,1,#str)}
for j = 1, reuses do
for i = 1, #tbl do
c = tbl[i]
end
end
end
elapsed = os.clock() - x
print(string.format("V5: elapsed time: %.3f", elapsed))
x = os.clock()
for k = 1, attempts do
tbl = {stringbyte(str, 1, #str)}
for i = 1, #tbl do
tbl[i] = stringchar(tbl[i])
end
for j = 1, reuses do
for i = 1, #tbl do
c = tbl[i]
end
end
end
elapsed = os.clock() - x
print(string.format("V5b: elapsed time: %.3f", elapsed))
Đầu ra ví dụ (Lua 5.3.4, Windows) :
Raw speed:
V1: elapsed time: 3.713
V2: elapsed time: 5.089
V3: elapsed time: 5.222
V4: elapsed time: 4.066
V5: elapsed time: 2.627
V5b: elapsed time: 3.627
Creating cache table (10 reuses):
V1: elapsed time: 20.381
V2: elapsed time: 23.913
V3: elapsed time: 25.221
V4: elapsed time: 20.551
V5: elapsed time: 13.473
V5b: elapsed time: 18.046
Kết quả:
Trong trường hợp của tôi, tốc độ thô string.byte
và string.sub
nhanh nhất. Khi sử dụng bảng bộ nhớ cache và sử dụng lại nó 10 lần mỗi vòng lặp, string.byte
phiên bản nhanh nhất ngay cả khi chuyển đổi mã ký tự trở lại ký tự (không phải lúc nào cũng cần thiết và tùy thuộc vào cách sử dụng).
Như bạn có thể đã nhận thấy, tôi đã đưa ra một số giả định dựa trên các điểm chuẩn trước đây của mình và áp dụng chúng cho mã:
- Các hàm thư viện nên luôn được bản địa hóa nếu được sử dụng bên trong các vòng lặp, vì nó nhanh hơn rất nhiều.
- Chèn phần tử mới vào bảng lua bằng cách sử dụng nhanh
tbl[idx] = value
hơn nhiều table.insert(tbl, value)
.
- Sử dụng vòng lặp qua bảng
for i = 1, #tbl
nhanh hơn một chút for k, v in pairs(tbl)
.
- Luôn thích phiên bản có ít lệnh gọi hàm hơn, vì bản thân lệnh gọi sẽ thêm một chút vào thời gian thực thi.
Hy vọng nó giúp.