Verilen cevaplarda zaten birçok iyi yaklaşım var ( burada , burada ve burada ). Öncelikle aradığınız şey hız ise , işi kesinlikle ham Lua kodundan çok daha hızlı olan Lua'nın C API'si aracılığıyla yapmayı düşünmelisiniz. Önceden yüklenmiş parçalarla çalışırken (örn. Yükleme işlevi ), fark o kadar büyük değil, ancak yine de önemli.
Saf Lua çözümlerine gelince , yaptığım bu küçük ölçütü paylaşmama izin verin. Bu tarihe verilen her cevabı kapsar ve birkaç optimizasyon ekler. Yine de dikkate alınması gereken temel şey şudur:
Dizideki karakterleri kaç kez yinelemeniz gerekecek?
- Cevap "bir kez" ise, banchmark'ın ilk kısmına bakmanız gerekir ("ham hız").
- Aksi takdirde, ikinci bölüm daha kesin bir tahmin sağlayacaktır, çünkü dizeyi tabloya ayrıştırır, bu da yinelemesi çok daha hızlıdır. Bunun için @ Jarriz'in önerdiği gibi basit bir işlev yazmayı da düşünmelisiniz.
İşte tam kod:
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))
Örnek çıktı (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
Sonuç:
Benim durumumda, string.byte
ve string.sub
ham hız açısından en hızlıydı. Önbellek tablosunu kullanırken ve döngü başına 10 kez yeniden kullanırken, string.byte
sürüm, karakter kodlarını karakterlere geri dönüştürürken bile en hızlıydı (bu her zaman gerekli değildir ve kullanıma bağlıdır).
Muhtemelen fark ettiğiniz gibi, önceki kıyaslamalarıma dayanarak bazı varsayımlar yaptım ve bunları koda uyguladım:
- Kütüphane fonksiyonları döngülerin içinde kullanılıyorsa her zaman yerelleştirilmelidir, çünkü çok daha hızlıdır.
- Lua tabloya yeni element takılması çok daha hızlı kullanıyor
tbl[idx] = value
daha table.insert(tbl, value)
.
- Tablo kullanarak döngü yapmak
for i = 1, #tbl
biraz daha hızlıdır for k, v in pairs(tbl)
.
- Her zaman daha az işlev çağrısı içeren sürümü tercih edin, çünkü çağrının kendisi yürütme süresine biraz ekler.
Umarım yardımcı olur.