2008-09-23 34 views
7

Tôi đã có một chương trình Lua mà có vẻ chậm hơn nó phải là. Tôi nghi ngờ vấn đề là tôi đang thêm giá trị vào một mảng kết hợp tại một thời điểm và bảng phải phân bổ bộ nhớ mới mỗi lần.Làm thế nào để bạn kích thước trước một mảng trong Lua?

Có dường như là một chức năng table.setn, nhưng nó không thành công dưới Lua 5.1.3:

stdin:1: 'setn' is obsolete 
stack traceback: 
     [C]: in function 'setn' 
     stdin:1: in main chunk 
     [C]: ? 

tôi thu thập từ Google tìm kiếm tôi đã làm điều đó chức năng này đã được khấu hao trong Lua 5.1, nhưng tôi không thể tìm thấy những gì (nếu có) thay thế các chức năng.

Bạn có biết cách kích thước trước một bảng trong Lua không?

Ngoài ra, có cách nào khác để tránh phân bổ bộ nhớ khi bạn thêm đối tượng vào bảng không?

+0

Tôi đọc điều này cho vui vào ngày khác, nhưng nếu bạn quan tâm đến hiệu suất lua, bạn nên kiểm tra bài viết này về việc thực hiện lua, nó đi qua khá một vài cấu trúc dữ liệu nội bộ. http://www.lua.org/doc/jucs05.pdf – Falaina

Trả lời

5

Tôi không nghĩ rằng bạn có thể - nó không phải là một mảng, nó là một mảng kết hợp, giống như một băm perl hoặc một mảng awk.

http://www.lua.org/manual/5.1/manual.html#2.5.5

Tôi không nghĩ rằng bạn có thể đặt trước kích thước của nó có ý nghĩa từ phía Lua.

Nếu bạn đang phân bổ mảng ở phía bên C, tuy nhiên, các

void lua_createtable (lua_State *L, int narr, int nrec); 

có thể là những gì bạn cần.

Tạo bảng trống mới và đẩy vào ngăn xếp. Bảng mới có không gian được phân bổ trước cho mảng narr các phần tử và các phần tử không phải mảng. Phân bổ trước này hữu ích khi bạn biết chính xác có bao nhiêu phần tử mà bảng sẽ có. Nếu không, bạn có thể sử dụng chức năng lua_newtable.

+0

Mặt khác, System.Collection.Hashtable của .NET có một hàm tạo với tham số dung lượng. – Constantin

1

Vẫn còn một luaL_setn nội bộ và bạn có thể biên dịch Lua để nó được hiển thị dưới dạng table.setn. Nhưng có vẻ như nó sẽ không giúp ích cho số vì mã này dường như không thực hiện trước khi mở rộng.

(Ngoài ra setn như nhận xét trên setn có liên quan đến phần mảng của một bảng Lua, và bạn nói rằng bạn đang sử dụng bảng như một kết mảng)

Phần tốt là ngay cả nếu bạn thêm từng phần tử, Lua không tăng mảng theo cách đó. Thay vào đó, nó sử dụng một chiến lược hợp lý hơn. Bạn vẫn còn nhận được nhiều phân bổ cho một mảng lớn hơn nhưng hiệu suất tốt hơn so với số nhận phân bổ mới mỗi lần.

+0

Đối với các tình huống chung, đó là một chiến lược hợp lý, nhưng đối với chương trình cụ thể này, tôi biết chính xác mức độ cần thiết của bảng. –

5
static int new_sized_table(lua_State *L) 
{ 
    int asize = lua_tointeger(L, 1); 
    int hsize = lua_tointeger(L, 2); 
    lua_createtable(L, asize, hsize); 
    return(1); 
} 

... 

lua_pushcfunction(L, new_sized_table); 
lua_setglobal(L, "sized_table"); 

Sau đó, trong Lua,

array = function(size) return sized_table(size,0) end 

a = array(10) 

Như một cách nhanh chóng hack để có được điều này chạy bạn có thể thêm C để lua.c.

+0

Có bất kỳ lý do nào tại sao điều này không được cung cấp theo mặc định không? Trong, cho phép nói, bảng thư viện. – Marko

9

Hãy để tôi tập trung hơn vào câu hỏi của bạn:

thêm giá trị cho một mảng kết hợp cùng một lúc

Bàn trong Lua là kết hợp, nhưng sử dụng chúng trong một hình thức mảng (1 ..N) được tối ưu hóa. Họ có hai mặt, trong nội bộ.

Vì vậy .. Nếu bạn thực sự đang thêm giá trị tương đối, hãy làm theo các quy tắc ở trên.

Nếu bạn đang sử dụng chỉ mục 1..N, bạn có thể buộc điều chỉnh kích thước một lần bằng cách đặt t [100000] = một cái gì đó. Điều này sẽ làm việc cho đến khi giới hạn kích thước mảng được tối ưu hóa, được xác định trong các nguồn Lua (2^26 = 67108864). Sau đó, mọi thứ đều kết hợp.

p.s. Phương thức 'setn' cũ chỉ xử lý phần mảng, vì vậy nó không sử dụng cho việc sử dụng kết hợp (bỏ qua các câu trả lời đó).

p.p.s. Bạn đã nghiên cứu các mẹo chung để giữ hiệu suất Lua cao chưa? tức là biết tạo bảng và sử dụng lại một bảng hơn là tạo bảng mới, sử dụng 'in cục bộ = in' và như vậy để tránh truy cập toàn cầu.

+0

Tôi đã không nhìn vào hiệu suất Lua nói chung, nhưng tôi chắc chắn quan tâm.Trong thực tế, tôi chỉ hỏi câu hỏi: http://stackoverflow.com/questions/154672/what-can-i-do-to-increase-the-performance-of-a-lua-program –

+9

Câu trả lời này không đúng (nữa?), theo "lời khuyên hiệu suất Lua" (có được nó ở đây http://www.lua.org/gems/), Lua phân tích bảng và đặt giá trị vào phần băm nếu phần mảng có ít hơn array_N/2, do đó, xây dựng 't = {}; t [100000] = true' sẽ dẫn đến một phần mảng trống và phần băm với một phần tử. – dualed

1

Mặc dù điều này không trả lời câu hỏi chính của bạn, nó trả lời câu hỏi thứ hai của bạn:

Ngoài ra, có một số cách khác để tránh cấp phát bộ nhớ khi bạn thêm một đối tượng vào một bảng?

Nếu bạn chạy Lua trong ứng dụng tùy chỉnh, như tôi có thể đoán từ mã C, tôi đề nghị bạn thay thế người cấp phát bằng bộ phân bổ giá trị nhỏ của Loki. Điều này cải thiện hiệu suất bằng cách tránh các chuyến đi vòng quanh hạt nhân, và làm cho tôi trở thành một lập trình viên hạnh phúc hơn :)

Dù sao tôi đã thử các trình phân bổ khác, nhưng chúng tổng quát hơn và cung cấp sự đảm bảo không có lợi cho các ứng dụng Lua (chẳng hạn như chuỗi an toàn, và phân bổ đối tượng lớn, vv ...), cũng viết phân bổ đối tượng nhỏ của riêng bạn có thể là một tuần tốt để lập trình và gỡ lỗi để có được đúng, và sau khi tìm kiếm giải pháp có sẵn của Loki cho vấn đề này.

2

Nếu bạn khai báo bảng của bạn trong mã với một số tiền cụ thể các hạng mục, như vậy:

local tab = { 0, 1, 2, 3, 4, 5, ... , n } 

sau đó Lua sẽ tạo ra bảng với bộ nhớ đã được phân bổ cho ít nhất n mục.

Tuy nhiên, Lua sử dụng kỹ thuật phân bổ bộ nhớ tăng dần 2x, vì vậy việc thêm mục vào bảng sẽ hiếm khi buộc phải phân bổ lại.

Các vấn đề liên quan