Proposal : Constant(immtable) object

92 views
Skip to first unread message

云风 Cloud Wu

unread,
Dec 8, 2025, 11:28:44 PM (8 days ago) Dec 8
to lu...@googlegroups.com
I really enjoy the external string feature in Lua 5.5, but I believe
there is still room for improvement, particularly in scenarios
involving multiple Lua virtual machines.

I would like to see certain constant objects separated from the Lua
state entirely, so they are not subject to garbage collection.
Instead, they should be managed through an additional mechanism to
ensure proper lifecycle control.

When an object is marked as a constant object, it should only be
collected during lua_close and should not be subject to the standard
garbage collection process. The existing luaC_fix API already achieves
this by marking objects as "fixed" in the GC system. However, in the
current Lua implementation, the luaC_fix API is used sparingly.

I think the function prototypes loaded via lua_load, as well as the
constant strings referenced within them, could all be marked as
fixed/constant objects.

I would like to propose adding a "readonly table" feature. When a
table's all keys and values are constant objects, it could be
converted into a readonly table and marked as a constant object. This
would allow the Lua runtime to treat such tables as immutable,
preventing unintended modifications while maintaining performance
optimizations for constant data structures.

You can convert a constant object into a C pointer using lua_topointer
(or a newly added API), and then push it into the Lua state via an API
like lua_pushconstantobject. This would enable efficient cross-Lua
state transmission of constant objects, as the C pointer would serve
as a lightweight reference to the immutable data.

I believe this new mechanism could significantly accelerate the
startup time of new Lua virtual machines in multi-Lua VM scenarios.
For example, in a web server framework, each request could quickly
create a new Lua state by reusing pre-prepared constant objects in the
framework's Lua state. This would eliminate the need to re-initialize
code and data structures for every request, as the necessary code and
data would already be stored as constant objects in the framework's
Lua state, enabling rapid reuse across new Lua states.

For scenarios that rely on massive and complex data structures, this
mechanism can significantly reduce the time spent on garbage
collection (GC) marking. Since most of the data is immutable, the GC
cycle can directly skip these objects during the marking phase. This
optimization would minimize the overhead of scanning and tracking
immutable data, allowing the GC to focus only on mutable objects and
thus improving overall performance.


--
http://blog.codingnow.com

Sainan

unread,
Dec 9, 2025, 3:40:45 AM (8 days ago) Dec 9
to lu...@googlegroups.com
Still sounds slower than coroutines.

-- Sainan

云风 Cloud Wu

unread,
Dec 9, 2025, 5:34:52 AM (7 days ago) Dec 9
to lu...@googlegroups.com
'Sainan' via lua-l <lu...@googlegroups.com> 于2025年12月9日周二 16:40写道:
>
> Still sounds slower than coroutines.

Creating a Lua virtual machine is evidently slower than creating
coroutines, but it enables better parallel task processing across
multiple CPU cores, and Lua states provide enhanced resource
isolation.

For a web server, we can design a hybrid framework that routes
multiple requests from the same user to a single Lua state, with
multiple coroutines handling the processing.

This approach not only improves startup speed (which can be optimized
by pre-warming some empty Lua states), but also significantly reduces
memory usage when many Lua states are created simultaneously.

--
http://blog.codingnow.com

Martin Eden

unread,
Dec 9, 2025, 7:02:30 AM (7 days ago) Dec 9
to lu...@googlegroups.com
On 2025-12-09 06:28, 云风 Cloud Wu wrote:
> [...]
>
> I would like to see certain constant objects separated from the Lua
> state entirely, so they are not subject to garbage collection.
> Instead, they should be managed through an additional mechanism to
> ensure proper lifecycle control.
>
> When an object is marked as a constant object, it should only be
> collected during lua_close and should not be subject to the standard
> garbage collection process. The existing luaC_fix API already achieves
> this by marking objects as "fixed" in the GC system. However, in the
> current Lua implementation, the luaC_fix API is used sparingly.
>
> I think the function prototypes loaded via lua_load, as well as the
> constant strings referenced within them, could all be marked as
> fixed/constant objects.
>
> I would like to propose adding a "readonly table" feature. When a
> table's all keys and values are constant objects, it could be
> converted into a readonly table and marked as a constant object. This
> would allow the Lua runtime to treat such tables as immutable,
> preventing unintended modifications while maintaining performance
> optimizations for constant data structures.
>
> [...]
>
Hello Cloud,

We have `__mode` for tables. Lemme remind what it is for readers.

  `__mode` is string key for metatable. It's string. Each it's character
  is scanned and processed. Special characters are `k` and `v`.

  `k` - keys of table do not increase reference count for collector
  `v` - values do not increase refcount

  Tables with such __mode are called "weak" tables.

What if we add "tempered" tables?

  `K` - keys are locked for modification
  `V` - values are locked for modification

Of course when key or value is not locked and is collected or
assigned to "nil" whole key-value entry is removed from table.

So for "immutable" tables you would want (__mode == 'KV').

-- Martin


Francisco Olarte

unread,
Dec 9, 2025, 8:04:30 AM (7 days ago) Dec 9
to lu...@googlegroups.com
Without entering too deep...

On Tue, 9 Dec 2025 at 13:02, 'Martin Eden' via lua-l <lu...@googlegroups.com> wrote:
What if we add "tempered" tables?

   `K` - keys are locked for modification
   `V` - values are locked for modification

I think you should specify it a bit more.

Do you mean K = keyset is locked for modification?
I mean, given { a = 1 }, you cannot modify key a, so
I suppose you mean preventing t.a=nil and t.b=1, which
really does not modify key set.
Or do you mean:
kt={x=1} t[kt]=1, lock K in t....
and then prevent kt.x=2? ( key modification, always hairy )



Do you mean V = Values for a key cannot be changed? 

t.a = 5, I assume V intercepts t.a=6.
- Does it also prevent t.a = nil ( deletion ) ?.
- If t.a={}, do you want to prevent t.a.a=1 ?
- if t is empty, does it prevent t.a=5 ?
I mean 

FOS

Luiz Henrique de Figueiredo

unread,
Dec 9, 2025, 8:25:45 AM (7 days ago) Dec 9
to lu...@googlegroups.com
> `K` - keys are locked for modification
> `V` - values are locked for modification

This can already be done with proxy tables and metamethods.

Martin Eden

unread,
Dec 9, 2025, 8:37:36 AM (7 days ago) Dec 9
to lu...@googlegroups.com
>> `K` - keys are locked for modification
>> `V` - values are locked for modification
> This can already be done with proxy tables and metamethods.

That's correct. But "constant" tables is recurring theme and maybe it
makes sense to have shortcut for them.


Martin Eden

unread,
Dec 9, 2025, 9:13:24 AM (7 days ago) Dec 9
to lu...@googlegroups.com
On 2025-12-09 15:03, Francisco Olarte wrote:
> I think you should specify it a bit more.
>
> Do you mean K = keyset is locked for modification?
>
> I mean, given { a = 1 }, you cannot modify key a, so
> I suppose you mean preventing t.a=nil and t.b=1, which
> really does not modify key set.

`t.a = nil` does not modify keyset. But of course it semantically
removes key-value pair.

Maybe it makes sense to forbid nil assignment to key-locked field.
As we have no means to distinguish `{}` from `{a=nil}`.

`t.b = 1` does modify keyset by adding key `b`. It supposed
to be blocked.

> Or do you mean:
> kt={x=1} t[kt]=1, lock K in t....
> and then prevent kt.x=2? ( key modification, always hairy )

`kt.x = 2` does not modify keyset. It modifies data at address
referenced by key. It is allowed.

> Do you mean V = Values for a key cannot be changed?
>
> t.a = 5, I assume V intercepts t.a=6.
> - Does it also prevent t.a = nil ( deletion ) ?.

Yes it does.

> - If t.a={}, do you want to prevent t.a.a=1 ?

No I don't. `t.a.a = 1` modifies referenced data. We don't care about it.
If someone wants to lock subtable he/she should lock subtable.

So for `t = { f = { ff = 1 }` `t.f.ff = nil` is allowed. But not `t.f = {}`.

> - if t is empty, does it prevent t.a=5 ?

No it does not. Locking values prevents changing values for key-value pairs.
If keyset is not locked you can `t.a = 5`. But not `t.a = 5; t.a = nil`.


So for key-value table pairs `V` prevents changing values and
`K` prevents adding/removing keys.

(Sorry for sort of derailing this thread Cloud Wu, I'm replying to specific
questions on alternative approach offered to your proposal.)

-- Martin

Francisco Olarte

unread,
Dec 9, 2025, 9:31:14 AM (7 days ago) Dec 9
to lu...@googlegroups.com
Hi Martin:

On Tue, 9 Dec 2025 at 15:13, 'Martin Eden' via lua-l <lu...@googlegroups.com> wrote:
On 2025-12-09 15:03, Francisco Olarte wrote:
 > I think you should specify it a bit more.
 >
 > Do you mean K = keyset is locked for modification?
 >
 > I mean, given { a = 1 }, you cannot modify key a, so
 > I suppose you mean preventing t.a=nil and t.b=1, which
 > really does not modify key set.

`t.a = nil` does not modify keyset. But of course it semantically
removes key-value pair.

mmm, this is why I hate removing by assign nil. By key set I mean, more or less:
keyset={}; for k,_ in pairs(t) do table.insert(keyset, k) end
More or less what perl return for keys %t, or java for Map.keySet() in Java.
With that definition t.a=nil modifies it.

 Maybe it makes sense to forbid nil assignment to key-locked field.
As we have no means to distinguish `{}` from `{a=nil}`.

It may, just define modifying lock.

`t.b = 1` does modify keyset by adding key `b`. It supposed
to be blocked.

 
 > Or do you mean:
 > kt={x=1} t[kt]=1, lock K in t....
 > and then prevent kt.x=2? ( key modification, always hairy )

`kt.x = 2` does not modify keyset. It modifies data at address
referenced by key. It is allowed.
K. That's what I assumed. Anyway, mutable keys in a map is a hairy bussiness, it is ok in normal lua, as table identity is used, I'm not sure if recent versions provide some kind of value identity, like C++ or others.


  > Do you mean V = Values for a key cannot be changed?
 >
 > t.a = 5, I assume V intercepts t.a=6.
 > - Does it also prevent t.a = nil ( deletion ) ?.

Yes it does.
Ok, as assumed.

 > - If t.a={}, do you want to prevent t.a.a=1 ?

No I don't. `t.a.a = 1` modifies referenced data. We don't care about it.
If someone wants to lock subtable he/she should lock subtable.
OK, nearly assumed.

 
So for `t = { f = { ff = 1 }` `t.f.ff = nil` is allowed. But not `t.f = {}`.
OK, mor or less preserve current t.f == future t.f

 
So for key-value table pairs `V` prevents changing values and
`K` prevents adding/removing keys.

Much better understood now.
FOS

云风 Cloud Wu

unread,
Dec 9, 2025, 9:55:00 AM (7 days ago) Dec 9
to lu...@googlegroups.com
'Martin Eden' via lua-l <lu...@googlegroups.com> 于2025年12月9日周二 21:37写道:
The key point is that an immutable table requires all the keys ,
values and the metatable to be immutable. However, metamethod
functions with upvalues cannot be immutable.


--
http://blog.codingnow.com
Reply all
Reply to author
Forward
0 new messages