Regarding ngx.var

900 views
Skip to first unread message

Ajay k

unread,
Aug 10, 2015, 5:20:15 PM8/10/15
to openresty-en
Hi ,

I was going through the documentation of https://github.com/openresty/lua-nginx-module#ngxvarvariable

Here is the use case i just want some understanding on the memory usage and best practice

-- snippet 1 -- 

local ngx_var  = ngx.var
local uri = ngx_var.uri
local args = ngx_var.args

local experssion1 = ngx_var.expression1
local experssion2 = ngx_var.expression2
local experssion3 = ngx_var.expression3


--snippet 2 --

local uri  = ngx.var.uri
local args = ngx.var.args

local experssion1 = ngx.var.expression1
local experssion2 = ngx.var.expression2
local experssion3 = ngx.var.expression3
...

the Document Clearly states 
 WARNING When reading from an Nginx variable, Nginx will allocate memory in the per-request memory pool which is freed only at request termination. So when you need to read from an Nginx variable repeatedly in your Lua code, cache the Nginx variable value to your own Lua variable, for example,

We are currently repeatedly reading from the nginx variable repeatedly as shown in  snippet 2 , want to start using snippet 1 , but my team mates think its more of a syntatic sugar than a performance gain , Can you please help me understanding which is better for performance


Thanks,
Ajay 

DeJiang Zhu

unread,
Aug 10, 2015, 10:10:01 PM8/10/15
to openre...@googlegroups.com
hi,

1. I do think snippet 1 will be a little bit better than snippet 2, but has nothing to do with the WARNING

2. `repeatedly` in the WARNING, means like this:

local experssion = ngx.var.expression  -- (allocate memory in this step)
for i = 1, n do
    -- use experssion here  -- (no more allocate)
end


--
You received this message because you are subscribed to the Google Groups "openresty-en" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openresty-en...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ajay k

unread,
Aug 11, 2015, 5:06:34 PM8/11/15
to openre...@googlegroups.com
Hi ,

Thanks for your response ,


We were reevaluating the ngx.var.* again in couple of code blocks  , This might not be the right example but something similar 

local experssion = ngx.var.expression  -- (allocate memory in this step)
for i = 1, n do
    -- use experssion here  -- (no more allocate)
 
       -- Something like this 
       local expressionagain = ngx.var.expression
   
end
--
Thanks,
Ajay K

Lord Nynex

unread,
Aug 11, 2015, 6:07:05 PM8/11/15
to openre...@googlegroups.com
Hello,

I hope someone corrects me if I'm wrong on this. 

I believe Snippet1 is less efficient. AFAIK, internally, ngx.var is exposed as a Lua table that surfaces values through a metamethod. So in this case, you would not be avoiding the expensive meta method lookup. I may be thinking about ngx.ctx, or perhaps they're the same. Either way, snippet 2 is more direct and likely more efficient. 


--

bjoe2k4

unread,
Aug 11, 2015, 6:50:25 PM8/11/15
to openresty-en
Guys, if you really want to know, what's better, benchmark your code!

    location = /bench {
        content_by_lua
'
            local ngx_var = ngx.var
            local ngx_var_uri = ngx.var.uri
            local n = 10000000
           
            ngx.update_time()
            local start = ngx.now()
            for i=1,n do
                local tmp = ngx.var.uri
            end
            ngx.update_time()
            local t = ngx.now() - start
           
            ngx.say("ngx.var.uri: ",t)
           
            ngx.update_time()
            local start = ngx.now()
            for i=1,n do
                local tmp = ngx_var.uri
            end
            ngx.update_time()
            local t = ngx.now() - start
           
            ngx.say("ngx_var.uri: ",t)
           
            ngx.update_time()
            local start = ngx.now()
            for i=1,n do
                local tmp = ngx_var_uri
            end
            ngx.update_time()
            local t = ngx.now() - start
           
            ngx.say("ngx_var_uri: ",t)
        '
;    

ngx.var.uri: 0.7279999256134
ngx_var
.uri: 0.66199994087219
ngx_var_uri
: 0.005000114440918

Therefore it doesn't really matter if you use ngx.var.xxx or ngx_var.xxx, it's comparably slow (on my systems the values fluctuate a bit).

Therefore: localize your ngx.var.xxx variables whenever possible at the outermost (out of loops) place!

Anorov

unread,
Aug 12, 2015, 9:27:01 PM8/12/15
to openresty-en
Shouldn't LuaJIT cache table lookups like those in many cases? I was under the impression that tight loops like those would cause it to typically hoist it out of the loop and cache the lookup automatically.

Yichun Zhang (agentzh)

unread,
Aug 13, 2015, 5:44:50 AM8/13/15
to openresty-en
Hello!

On Thu, Aug 13, 2015 at 9:27 AM, Anorov wrote:
> Shouldn't LuaJIT cache table lookups like those in many cases? I was under
> the impression that tight loops like those would cause it to typically hoist
> it out of the loop and cache the lookup automatically.
>

This metamethod for ngx.var.foo has side-effects like allocating
memory in nginx's request pool and it's never safe for the LuaJIT
compiler to assume that it is a constant and side-effect free.

Regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages