Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: tarantool-patches@dev.tarantool.org, gorcunov@gmail.com,
	sergepetrenko@tarantool.org
Subject: [Tarantool-patches] [PATCH 08/16] uuid: replace static_alloc with ffi stash
Date: Sat, 20 Mar 2021 01:42:45 +0100	[thread overview]
Message-ID: <dcc2a3e300ca287cd064a27645a89125c5aa86a7.1616200860.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1616200860.git.v.shpilevoy@tarantool.org>

static_alloc() appears not to be safe to use in Lua, because it
does not provide any ownership protection for the returned values.

The problem appears when something is allocated, then Lua GC
starts, and some __gc handlers might also use static_alloc(). In
Lua and in C - both lead to the buffer being corrupted in its
original usage place.

The patch is a part of activity of getting rid of static_alloc()
in Lua. It removes it from uuid Lua module and makes it use the
new FFI stash feature, which helps to cache frequently used and
heavy to allocate FFI values.

ffi.new() is not used, because

- It produces a new GC object;

- ffi.new('struct tt_uuid') costs around 300ns while FFI stash
  costs around 0.8ns (although it is magically fixed when
  ffi.new('struct tt_uuid[1]') is used);

- Without JIT ffi.new() costs about the same as the stash, ~280ns
  for small objects like tt_uuid.

The patch makes uuid perf a bit better in the places where
static_alloc() was used, because its cost was around 7ns for one
allocation.
---
 src/lua/uuid.lua | 102 ++++++++++++++++++++++++++++-------------------
 1 file changed, 62 insertions(+), 40 deletions(-)

diff --git a/src/lua/uuid.lua b/src/lua/uuid.lua
index 9cebf3ace..74f8c924c 100644
--- a/src/lua/uuid.lua
+++ b/src/lua/uuid.lua
@@ -1,7 +1,7 @@
 -- uuid.lua (internal file)
 
 local ffi = require("ffi")
-local static_alloc = require('buffer').static_alloc
+local buffer = require('buffer')
 local builtin = ffi.C
 
 ffi.cdef[[
@@ -27,6 +27,9 @@ extern const struct tt_uuid uuid_nil;
 local uuid_t = ffi.typeof('struct tt_uuid')
 local UUID_STR_LEN = 36
 local UUID_LEN = ffi.sizeof(uuid_t)
+local uuid_stash = buffer.ffi_stash_new(uuid_t)
+local uuid_stash_take = uuid_stash.take
+local uuid_stash_put = uuid_stash.put
 
 local is_uuid = function(value)
     return ffi.istype(uuid_t, value)
@@ -66,10 +69,12 @@ local uuid_tobin = function(uu, byteorder)
         return error('Usage: uuid:bin([byteorder])')
     end
     if need_bswap(byteorder) then
-        local uuidbuf = static_alloc('struct tt_uuid')
+        local uuidbuf = uuid_stash_take()
         ffi.copy(uuidbuf, uu, UUID_LEN)
         builtin.tt_uuid_bswap(uuidbuf)
-        return ffi.string(ffi.cast('char *', uuidbuf), UUID_LEN)
+        uu = ffi.string(ffi.cast('char *', uuidbuf), UUID_LEN)
+        uuid_stash_put(uuidbuf)
+        return uu
     end
     return ffi.string(ffi.cast('char *', uu), UUID_LEN)
 end
@@ -93,42 +98,29 @@ local uuid_isnil = function(uu)
     return builtin.tt_uuid_is_nil(uu)
 end
 
-local fromstr = function(str)
-    local uu = static_alloc('struct tt_uuid')
-    local rc = builtin.tt_uuid_from_string(str, uu)
-    if rc ~= 0 then
-        return nil
-    end
-    return uu
-end
-
-local to_uuid = function(value)
-    if is_uuid(value) then
-        return value
-    end
-    if type(value) == 'string' then
-        return fromstr(value)
-    end
-    return nil
-end
-
-local check_uuid = function(value, index, err_lvl)
-    value = to_uuid(value)
-    if value ~= nil then
-        return value
-    end
-
+local function error_convert_arg(arg_index)
     local err_fmt = 'incorrect value to convert to uuid as %d argument'
-    error(err_fmt:format(index), err_lvl)
+    error(err_fmt:format(arg_index), 3)
 end
 
 local uuid_eq = function(lhs, rhs)
-    rhs = to_uuid(rhs)
-    if rhs == nil then
+    if not is_uuid(lhs) then
+        lhs, rhs = rhs, lhs
+    elseif is_uuid(rhs) then
+        return builtin.tt_uuid_is_equal(lhs, rhs)
+    end
+    if type(rhs) ~= 'string' then
         return false
     end
-    lhs = check_uuid(lhs, 1, 3)
-    return builtin.tt_uuid_is_equal(lhs, rhs)
+    local buf = uuid_stash_take()
+    local rc = builtin.tt_uuid_from_string(rhs, buf) == 0
+    if rc then
+        rc = builtin.tt_uuid_is_equal(lhs, buf)
+    else
+        rc = false
+    end
+    uuid_stash_put(buf)
+    return rc
 end
 
 local uuid_new = function()
@@ -138,20 +130,50 @@ local uuid_new = function()
 end
 
 local uuid_new_bin = function(byteorder)
-    local uuidbuf = static_alloc('struct tt_uuid')
+    local uuidbuf = uuid_stash_take()
     builtin.tt_uuid_create(uuidbuf)
-    return uuid_tobin(uuidbuf, byteorder)
+    local res = uuid_tobin(uuidbuf, byteorder)
+    uuid_stash_put(uuidbuf)
+    return res
 end
 local uuid_new_str = function()
-    local uuidbuf = static_alloc('struct tt_uuid')
+    local uuidbuf = uuid_stash_take()
     builtin.tt_uuid_create(uuidbuf)
-    return uuid_tostring(uuidbuf)
+    local res = uuid_tostring(uuidbuf)
+    uuid_stash_put(uuidbuf)
+    return res
 end
 
 local uuid_cmp = function(lhs, rhs)
-    lhs = check_uuid(lhs, 1, 4)
-    rhs = check_uuid(rhs, 2, 4)
-    return builtin.tt_uuid_compare(lhs, rhs)
+    local buf
+    if is_uuid(lhs) then
+        if is_uuid(rhs) then
+            -- Fast path.
+           return builtin.tt_uuid_compare(lhs, rhs)
+        end
+        if type(rhs) ~= 'string' then
+            return error_convert_arg(2)
+        end
+        buf = uuid_stash_take()
+        if builtin.tt_uuid_from_string(rhs, buf) ~= 0 then
+            uuid_stash_put(buf)
+            return error_convert_arg(2)
+        end
+        rhs = buf
+    else
+        if type(lhs) ~= 'string' then
+            return error_convert_arg(1)
+        end
+        buf = uuid_stash_take()
+        if builtin.tt_uuid_from_string(lhs, buf) ~= 0 then
+            uuid_stash_put(buf)
+            return error_convert_arg(1)
+        end
+        lhs = buf
+    end
+    local rc = builtin.tt_uuid_compare(lhs, rhs)
+    uuid_stash_put(buf)
+    return rc
 end
 local uuid_lt = function(lhs, rhs)
     return uuid_cmp(lhs, rhs) < 0
-- 
2.24.3 (Apple Git-128)


  parent reply	other threads:[~2021-03-20  0:50 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-20  0:42 [Tarantool-patches] [PATCH 00/16] Cord buffer, static alloc, and Lua GC bug Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 01/16] fio: don't use shared buffer in pread() Vladislav Shpilevoy via Tarantool-patches
2021-03-22  7:19   ` Cyrill Gorcunov via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 10/16] uri: replace static_alloc with ffi stash and ibuf Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 11/16] buffer: remove static_alloc() from Lua Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 12/16] lua: use lua_pushfstring() instead of tt_sprintf() Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 13/16] sio: rework sio_strfaddr() Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 14/16] sio: increase SERVICE_NAME_MAXLEN size Vladislav Shpilevoy via Tarantool-patches
2021-03-21 21:58   ` Cyrill Gorcunov via Tarantool-patches
2021-03-22 22:32     ` Vladislav Shpilevoy via Tarantool-patches
2021-03-23  6:56       ` Cyrill Gorcunov via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 15/16] sio: introduce and use sio_snprintf() Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 16/16] buffer: remove Lua registers Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 02/16] test: don't use IBUF_SHARED in the tests Vladislav Shpilevoy via Tarantool-patches
2021-03-22  7:35   ` Cyrill Gorcunov via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 03/16] tuple: pass global ibuf explicitly where possible Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 04/16] iconv: take errno before reseting the context Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 05/16] cord_buf: introduce cord_buf API Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 06/16] cord_buf: introduce ownership management Vladislav Shpilevoy via Tarantool-patches
2021-03-22 16:48   ` Serge Petrenko via Tarantool-patches
2021-03-22 22:32     ` Vladislav Shpilevoy via Tarantool-patches
2021-03-23  7:46       ` Serge Petrenko via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 07/16] buffer: implement ffi stash Vladislav Shpilevoy via Tarantool-patches
2021-03-23  0:29   ` Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` Vladislav Shpilevoy via Tarantool-patches [this message]
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 09/16] uuid: drop tt_uuid_str() from Lua Vladislav Shpilevoy via Tarantool-patches
2021-03-21 16:38 ` [Tarantool-patches] [PATCH 00/16] Cord buffer, static alloc, and Lua GC bug Vladislav Shpilevoy via Tarantool-patches
2021-03-22  7:52 ` Cyrill Gorcunov via Tarantool-patches
2021-03-22  7:56 ` Konstantin Osipov via Tarantool-patches
2021-03-22 17:17 ` Serge Petrenko via Tarantool-patches
2021-03-23 23:45 ` Vladislav Shpilevoy via Tarantool-patches
2021-03-24 13:28 ` Kirill Yukhin via Tarantool-patches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dcc2a3e300ca287cd064a27645a89125c5aa86a7.1616200860.git.v.shpilevoy@tarantool.org \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=gorcunov@gmail.com \
    --cc=sergepetrenko@tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH 08/16] uuid: replace static_alloc with ffi stash' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox