9

As the title says. If I have a table p in lua, is using

table.remove(p)

the same as

p[#p] = nil

if so which is quicker - I'd guess the second, but would like some reassurance.

By the 'same as' I mean does the internal array storage shrink using assignment to nil? I can't seem to find this documented anywhere. Does setting the last element in an array to nil, or the last 10 elements in an array to nil mean the array will be shrunk, or does it always keep the storage and never shrink the array again?

I've assumed the array is contiguous, i.e. it has values stored in each array entry up to #p.

daven11
  • 2,905
  • 3
  • 26
  • 43
  • 1
    Why don't you write the trivial test program, try it, and tell us your results? If you post the code, maybe someone else can run it on a different platform, too (LuaJIT would be particularly interesting). – John Zwinck Aug 20 '11 at 03:11
  • 1
    indeed, I can do that, however I thought one of the smart lua folk here would know this off the top of their head, if not then I will need to investigate further. There's also two parts to the question - is it the same, I think so but again I'm not sure. – daven11 Aug 20 '11 at 03:24

5 Answers5

10

Setting the last element to nil will not be a function call. So in that way, it will certainly be faster than table.remove. How much that matters is up to you.

By the 'same as' I mean does the internal array storage shrink using assignment to nil? I can't seem to find this documented anywhere.

It isn't documented; this allows the implementation to change. All that Lua promises is that setting it to nil will decrease the size returned by subsequent calls to #p. Anything more than that is up to Lua, and is certainly subject to change without warning. It's nothing you should rely on.

However, I would respectfully suggest that if you're thinking about these kinds of micro-optimizations, you probably shouldn't be using a scripting language. A scripting language should be used for code where performance is not important enough to spend a great deal on.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks for that, I take your point about the optimization, my question was more about which way to go, and was my thinking correct, I wasn't quite sure which was the best way (I'll be doing a fair bit of this in my code, so knowing the tradeoffs is always better). An associated question is, is #p stored or does it scan the array to get the count, or is that again implementation dependent?Thanks again – daven11 Aug 20 '11 at 05:10
  • 3
    @daven11, in the current implementation, `#p` is computed each time, using a O(log n) algorithm. – lhf Aug 20 '11 at 11:31
4

p[#p] = nil will be faster, and identical for the case where table.remove is the last position

As an extra note, table.remove(func_call()) may do unexpected things if the function call returns multiple values.

daurnimator
  • 4,091
  • 18
  • 34
3

Going from the implementation of the Lua 5.1 VM as described in Lua Performance Tips by Roberto Ierusalimschy (chief architect of Lua), the table's allocated storage doesn't change until the next time the table is rehashed - and, as stated time and time again, you really shouldn't be thinking about this unless you have hard profiling data showing it's a significant problem.

As for the difference between table.remove(t) and t[#t] = nil, see my answer to What's the difference between `table.insert(t, i)` and `t[#t+1] = i`.

Community
  • 1
  • 1
Stuart P. Bentley
  • 10,195
  • 10
  • 55
  • 84
2

I think it is better to be consistent with adding are removing elements from array type tables. table.insert and table.remove make your code consistent and easier to read.

Re: tables Lua doesn't resize the table until you have added the first new element to it after having previously removed elements.

finnw
  • 47,861
  • 24
  • 143
  • 221
sylvanaar
  • 8,096
  • 37
  • 59
1

table.remove(p) returns the value that was removed. p[#p] = nil does not return anything.

finnw
  • 47,861
  • 24
  • 143
  • 221