Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [PATCH v2 0/2] buffer: port static allocator to Lua
@ 2019-05-18 22:15 Vladislav Shpilevoy
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 1/2] " Vladislav Shpilevoy
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Vladislav Shpilevoy @ 2019-05-18 22:15 UTC (permalink / raw)
  To: tarantool-patches; +Cc: kostja

The patchset allows to use the static allocator from Lua, and optimizes some
commonly appearing problems with passing parameters into FFI functions by a
pointer.

Changes in V2:
- Split in 2 commits.

V1: https://www.freelists.org/post/tarantool-patches/PATCH-11-buffer-port-static-allocator-to-Lua

Branch: http://github.com/tarantool/tarantool/tree/gerold103/static-allocator-lua

Vladislav Shpilevoy (2):
  buffer: port static allocator to Lua
  buffer: replace all ffi.new(type[1]) with cached union

 extra/exports            |  2 ++
 src/CMakeLists.txt       |  1 +
 src/box/lua/schema.lua   |  3 +-
 src/lua/buffer.c         | 42 +++++++++++++++++++++++++++
 src/lua/buffer.lua       | 61 ++++++++++++++++++++++++++++++++++++++++
 src/lua/crypto.lua       | 22 +++++++--------
 src/lua/digest.lua       |  7 +++--
 src/lua/fio.lua          |  3 +-
 src/lua/init.c           |  2 +-
 src/lua/msgpackffi.lua   | 50 +++++++++++++-------------------
 src/lua/socket.lua       | 36 ++++++++++++++----------
 src/lua/string.lua       | 10 ++++---
 src/lua/uri.lua          |  7 +++--
 src/lua/uuid.lua         |  9 +++---
 test/app/buffer.result   | 53 ++++++++++++++++++++++++++++++++++
 test/app/buffer.test.lua | 23 +++++++++++++++
 16 files changed, 256 insertions(+), 75 deletions(-)
 create mode 100644 src/lua/buffer.c
 create mode 100644 test/app/buffer.result
 create mode 100644 test/app/buffer.test.lua

-- 
2.20.1 (Apple Git-117)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] [PATCH v2 1/2] buffer: port static allocator to Lua
  2019-05-18 22:15 [tarantool-patches] [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy
@ 2019-05-18 22:15 ` Vladislav Shpilevoy
  2019-05-20  9:06   ` [tarantool-patches] " Konstantin Osipov
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union Vladislav Shpilevoy
  2019-05-21 16:56 ` [tarantool-patches] Re: [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy
  2 siblings, 1 reply; 7+ messages in thread
From: Vladislav Shpilevoy @ 2019-05-18 22:15 UTC (permalink / raw)
  To: tarantool-patches; +Cc: kostja

Static allocator gives memory blocks from cyclic BSS memory
block of 3 pages 4096 bytes each. It is much faster than
malloc, when a temporary buffer is needed.

This commit exposes the allocator to Lua, which suffers from
lack of ability to pass values by pointers into FFI functions,
nor has a stack to allocate small buffers like 'char[256]'.
Also these allocations complicate and slow down GC job.

Static allocator solves most of these problems provindg a way to
swiftly allocate temporary memory blocks.

A simple micro benchmark showed, that ffi.new() vs
buffer.static_alloc() is ~100 times slower, even on small
allocations of 1Kb, and ~1.5 times slower on tiny allocations
of 10 bytes. The results do not account GC. It is remarkable,
buffer.static_alloc() speed does not depend on size, while
ffi.new() strongly depends.
---
 extra/exports            |  2 ++
 src/CMakeLists.txt       |  1 +
 src/box/lua/schema.lua   |  3 ++-
 src/lua/buffer.c         | 42 ++++++++++++++++++++++++++++++++++++++++
 src/lua/buffer.lua       | 23 ++++++++++++++++++++++
 src/lua/digest.lua       |  7 ++++---
 src/lua/fio.lua          |  3 +--
 src/lua/init.c           |  2 +-
 src/lua/socket.lua       | 11 ++++++-----
 src/lua/string.lua       |  6 ++++--
 src/lua/uri.lua          |  7 ++++---
 src/lua/uuid.lua         |  9 +++++----
 test/app/buffer.result   | 26 +++++++++++++++++++++++++
 test/app/buffer.test.lua | 12 ++++++++++++
 14 files changed, 133 insertions(+), 21 deletions(-)
 create mode 100644 src/lua/buffer.c
 create mode 100644 test/app/buffer.result
 create mode 100644 test/app/buffer.test.lua

diff --git a/extra/exports b/extra/exports
index 4f41a17b3..5375a01e4 100644
--- a/extra/exports
+++ b/extra/exports
@@ -85,6 +85,8 @@ tnt_EVP_MD_CTX_free
 tnt_HMAC_CTX_new
 tnt_HMAC_CTX_free
 
+lua_static_aligned_alloc
+
 # Module API
 
 _say
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a6a18142b..492b8712e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -116,6 +116,7 @@ set (server_sources
      lua/utf8.c
      lua/info.c
      lua/string.c
+     lua/buffer.c
      ${lua_sources}
      ${PROJECT_SOURCE_DIR}/third_party/lua-yaml/lyaml.cc
      ${PROJECT_SOURCE_DIR}/third_party/lua-yaml/b64.c
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index f31cf7f2c..fa6c7c9a4 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -7,6 +7,7 @@ local fun = require('fun')
 local log = require('log')
 local fio = require('fio')
 local json = require('json')
+local static_alloc = require('buffer').static_alloc
 local session = box.session
 local internal = require('box.internal')
 local function setmap(table)
@@ -2103,7 +2104,7 @@ box.schema.user = {}
 
 box.schema.user.password = function(password)
     local BUF_SIZE = 128
-    local buf = ffi.new("char[?]", BUF_SIZE)
+    local buf = static_alloc('char', BUF_SIZE)
     builtin.password_prepare(password, #password, buf, BUF_SIZE)
     return ffi.string(buf)
 end
diff --git a/src/lua/buffer.c b/src/lua/buffer.c
new file mode 100644
index 000000000..5fd349261
--- /dev/null
+++ b/src/lua/buffer.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "small/static.h"
+
+/**
+ * Static inline functions like in static.h can't be exported.
+ * Here they are given a symbol to export.
+ */
+
+void *
+lua_static_aligned_alloc(size_t size, size_t alignment)
+{
+	return static_aligned_alloc(size, alignment);
+}
diff --git a/src/lua/buffer.lua b/src/lua/buffer.lua
index a72d8d1f9..5e9209387 100644
--- a/src/lua/buffer.lua
+++ b/src/lua/buffer.lua
@@ -33,6 +33,9 @@ ibuf_reinit(struct ibuf *ibuf);
 
 void *
 ibuf_reserve_slow(struct ibuf *ibuf, size_t size);
+
+void *
+lua_static_aligned_alloc(size_t size, size_t alignment);
 ]]
 
 local builtin = ffi.C
@@ -174,8 +177,28 @@ local function ibuf_new(arg, arg2)
     errorf('Usage: ibuf([size])')
 end
 
+--
+-- Allocate a chunk of static BSS memory, or use ordinal ffi.new,
+-- when too big size.
+-- @param type C type - a struct, a basic type, etc. Should be a
+--        string: 'int', 'char *', 'struct tuple', etc.
+-- @param size Optional argument, number of elements of @a type to
+--        allocate. 1 by default.
+-- @return Cdata pointer to @a type.
+--
+local function static_alloc(type, size)
+    size = size or 1
+    local bsize = size * ffi.sizeof(type)
+    local ptr = builtin.lua_static_aligned_alloc(bsize, ffi.alignof(type))
+    if ptr ~= nil then
+        return ffi.cast(type..' *', ptr)
+    end
+    return ffi.new(type..'[?]', size)
+end
+
 return {
     ibuf = ibuf_new;
     IBUF_SHARED = ffi.C.tarantool_lua_ibuf;
     READAHEAD = READAHEAD;
+    static_alloc = static_alloc,
 }
diff --git a/src/lua/digest.lua b/src/lua/digest.lua
index 8f199c0af..6ed91cfa2 100644
--- a/src/lua/digest.lua
+++ b/src/lua/digest.lua
@@ -3,6 +3,7 @@
 local ffi = require('ffi')
 local crypto = require('crypto')
 local bit = require('bit')
+local static_alloc = require('buffer').static_alloc
 
 ffi.cdef[[
     /* internal implementation */
@@ -179,7 +180,7 @@ local m = {
         end
         local blen = #bin
         local slen = ffi.C.base64_bufsize(blen, mask)
-        local str  = ffi.new('char[?]', slen)
+        local str  = static_alloc('char', slen)
         local len = ffi.C.base64_encode(bin, blen, str, slen, mask)
         return ffi.string(str, len)
     end,
@@ -190,7 +191,7 @@ local m = {
         end
         local slen = #str
         local blen = math.ceil(slen * 3 / 4)
-        local bin  = ffi.new('char[?]', blen)
+        local bin  = static_alloc('char', blen)
         local len = ffi.C.base64_decode(str, slen, bin, blen)
         return ffi.string(bin, len)
     end,
@@ -228,7 +229,7 @@ local m = {
         if n == nil then
             error('Usage: digest.urandom(len)')
         end
-        local buf = ffi.new('char[?]', n)
+        local buf = static_alloc('char', n)
         ffi.C.random_bytes(buf, n)
         return ffi.string(buf, n)
     end,
diff --git a/src/lua/fio.lua b/src/lua/fio.lua
index 38664a556..fce79c277 100644
--- a/src/lua/fio.lua
+++ b/src/lua/fio.lua
@@ -275,8 +275,7 @@ fio.dirname = function(path)
     if type(path) ~= 'string' then
         error("Usage: fio.dirname(path)")
     end
-    path = ffi.new('char[?]', #path + 1, path)
-    return ffi.string(ffi.C.dirname(path))
+    return ffi.string(ffi.C.dirname(ffi.cast('char *', path)))
 end
 
 fio.umask = function(umask)
diff --git a/src/lua/init.c b/src/lua/init.c
index be164bdfb..303369841 100644
--- a/src/lua/init.c
+++ b/src/lua/init.c
@@ -126,9 +126,9 @@ static const char *lua_modules[] = {
 	"errno", errno_lua,
 	"fiber", fiber_lua,
 	"env", env_lua,
+	"buffer", buffer_lua,
 	"string", string_lua,
 	"table", table_lua,
-	"buffer", buffer_lua,
 	"msgpackffi", msgpackffi_lua,
 	"crypto", crypto_lua,
 	"digest", digest_lua,
diff --git a/src/lua/socket.lua b/src/lua/socket.lua
index b2700e0c0..cbf8c0f29 100644
--- a/src/lua/socket.lua
+++ b/src/lua/socket.lua
@@ -10,6 +10,7 @@ local fiber = require('fiber')
 local fio = require('fio')
 local log = require('log')
 local buffer = require('buffer')
+local static_alloc = buffer.static_alloc
 
 local format = string.format
 
@@ -581,9 +582,10 @@ local function socket_linger(self, active, timeout)
         iactive = 0
     end
 
-    local value = ffi.new("linger_t[1]",
-        { { active = iactive, timeout = timeout } })
-    local len = 2 * ffi.sizeof('int')
+    local value = static_alloc('linger_t')
+    value[0].active = iactive
+    value[0].timeout = timeout
+    local len = ffi.sizeof('linger_t')
     local res = ffi.C.setsockopt(fd, level, info.iname, value, len)
     if res < 0 then
         self._errno = boxerrno()
@@ -836,8 +838,7 @@ local function socket_recv(self, size, flags)
     end
 
     self._errno = nil
-    local buf = ffi.new("char[?]", size)
-
+    local buf = static_alloc('char', size)
     local res = ffi.C.recv(fd, buf, size, iflags)
 
     if res == -1 then
diff --git a/src/lua/string.lua b/src/lua/string.lua
index 8216ace6a..bb4adfc78 100644
--- a/src/lua/string.lua
+++ b/src/lua/string.lua
@@ -1,4 +1,6 @@
 local ffi = require('ffi')
+local buffer = require('buffer')
+local static_alloc = buffer.static_alloc
 
 ffi.cdef[[
     const char *
@@ -290,7 +292,7 @@ local function string_hex(inp)
         error(err_string_arg:format(1, 'string.hex', 'string', type(inp)), 2)
     end
     local len = inp:len() * 2
-    local res = ffi.new('char[?]', len + 1)
+    local res = static_alloc('char', len + 1)
 
     local uinp = ffi.cast('const unsigned char *', inp)
     for i = 0, inp:len() - 1 do
@@ -333,7 +335,7 @@ local function string_fromhex(inp)
     end
     local len = inp:len() / 2
     local casted_inp = ffi.cast('const char *', inp)
-    local res = ffi.new('char[?]', len)
+    local res = static_alloc('char', len)
     for i = 0, len - 1 do
         local first = hexadecimals_mapping[casted_inp[i * 2]]
         local second = hexadecimals_mapping[casted_inp[i * 2 + 1]]
diff --git a/src/lua/uri.lua b/src/lua/uri.lua
index d2946cd2d..5967c8bf2 100644
--- a/src/lua/uri.lua
+++ b/src/lua/uri.lua
@@ -1,6 +1,7 @@
 -- uri.lua (internal file)
 
 local ffi = require('ffi')
+local static_alloc = require('buffer').static_alloc
 
 ffi.cdef[[
 struct uri {
@@ -32,12 +33,11 @@ uri_format(char *str, size_t len, struct uri *uri, bool write_password);
 
 local builtin = ffi.C;
 
-local uribuf = ffi.new('struct uri')
-
 local function parse(str)
     if str == nil then
         error("Usage: uri.parse(string)")
     end
+    local uribuf = static_alloc('struct uri')
     if builtin.uri_parse(uribuf, str) ~= 0 then
         return nil
     end
@@ -59,6 +59,7 @@ local function parse(str)
 end
 
 local function format(uri, write_password)
+    local uribuf = static_alloc('struct uri')
     uribuf.scheme = uri.scheme
     uribuf.scheme_len = string.len(uri.scheme or '')
     uribuf.login = uri.login
@@ -75,7 +76,7 @@ local function format(uri, write_password)
     uribuf.query_len = string.len(uri.query or '')
     uribuf.fragment = uri.fragment
     uribuf.fragment_len = string.len(uri.fragment or '')
-    local str = ffi.new('char[1024]')
+    local str = static_alloc('char', 1024)
     builtin.uri_format(str, 1024, uribuf, write_password and 1 or 0)
     return ffi.string(str)
 end
diff --git a/src/lua/uuid.lua b/src/lua/uuid.lua
index 956ad6e36..f8418cf4d 100644
--- a/src/lua/uuid.lua
+++ b/src/lua/uuid.lua
@@ -1,6 +1,7 @@
 -- uuid.lua (internal file)
 
 local ffi = require("ffi")
+local static_alloc = require('buffer').static_alloc
 local builtin = ffi.C
 
 ffi.cdef[[
@@ -33,7 +34,6 @@ 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 uuidbuf = ffi.new(uuid_t)
 
 local uuid_tostring = function(uu)
     if not ffi.istype(uuid_t, uu) then
@@ -69,9 +69,8 @@ local uuid_tobin = function(uu, byteorder)
         return error('Usage: uuid:bin([byteorder])')
     end
     if need_bswap(byteorder) then
-        if uu ~= uuidbuf then
-            ffi.copy(uuidbuf, uu, UUID_LEN)
-        end
+        local uuidbuf = static_alloc('struct tt_uuid')
+        ffi.copy(uuidbuf, uu, UUID_LEN)
         builtin.tt_uuid_bswap(uuidbuf)
         return ffi.string(ffi.cast('char *', uuidbuf), UUID_LEN)
     end
@@ -114,10 +113,12 @@ local uuid_new = function()
 end
 
 local uuid_new_bin = function(byteorder)
+    local uuidbuf = static_alloc('struct tt_uuid')
     builtin.tt_uuid_create(uuidbuf)
     return uuid_tobin(uuidbuf, byteorder)
 end
 local uuid_new_str = function()
+    local uuidbuf = static_alloc('struct tt_uuid')
     builtin.tt_uuid_create(uuidbuf)
     return uuid_tostring(uuidbuf)
 end
diff --git a/test/app/buffer.result b/test/app/buffer.result
new file mode 100644
index 000000000..e0aad9bc7
--- /dev/null
+++ b/test/app/buffer.result
@@ -0,0 +1,26 @@
+test_run = require('test_run').new()
+---
+...
+buffer = require('buffer')
+---
+...
+ffi = require('ffi')
+---
+...
+-- Alignment.
+_ = buffer.static_alloc('char') -- This makes buffer pos unaligned.
+---
+...
+p = buffer.static_alloc('int')
+---
+...
+ffi.cast('int', p) % ffi.alignof('int') == 0 -- But next alloc is aligned.
+---
+- true
+...
+-- Able to allocate bigger than static buffer - such allocations
+-- are on the heap.
+type(buffer.static_alloc('char', 13000))
+---
+- cdata
+...
diff --git a/test/app/buffer.test.lua b/test/app/buffer.test.lua
new file mode 100644
index 000000000..ba7299f33
--- /dev/null
+++ b/test/app/buffer.test.lua
@@ -0,0 +1,12 @@
+test_run = require('test_run').new()
+buffer = require('buffer')
+ffi = require('ffi')
+
+-- Alignment.
+_ = buffer.static_alloc('char') -- This makes buffer pos unaligned.
+p = buffer.static_alloc('int')
+ffi.cast('int', p) % ffi.alignof('int') == 0 -- But next alloc is aligned.
+
+-- Able to allocate bigger than static buffer - such allocations
+-- are on the heap.
+type(buffer.static_alloc('char', 13000))
-- 
2.20.1 (Apple Git-117)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union
  2019-05-18 22:15 [tarantool-patches] [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 1/2] " Vladislav Shpilevoy
@ 2019-05-18 22:15 ` Vladislav Shpilevoy
  2019-05-20 14:59   ` [tarantool-patches] " Vladislav Shpilevoy
  2019-05-21 16:56 ` [tarantool-patches] Re: [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy
  2 siblings, 1 reply; 7+ messages in thread
From: Vladislav Shpilevoy @ 2019-05-18 22:15 UTC (permalink / raw)
  To: tarantool-patches; +Cc: kostja

Lua, which suffers from lack of ability to pass values by
pointers into FFI functions, nor has an address operator '&' to
take an address of integer or char or anything. Because of that
a user need to either use ffi.new(type[1]) or use static buffer,
bur for such small allocations they are both too expensive and
aggravate GC problem.

Now buffer module provides preallocated basic types to use in FFI
functions. The commit is motivated by one another place where
ffi.new('int[1]') appeared, in SWIM module, to obtain payload
size as an out parameter of a C function.
---
 src/lua/buffer.lua       | 38 ++++++++++++++++++++++++++++++
 src/lua/crypto.lua       | 22 ++++++++----------
 src/lua/msgpackffi.lua   | 50 ++++++++++++++++------------------------
 src/lua/socket.lua       | 25 ++++++++++++--------
 src/lua/string.lua       |  4 ++--
 test/app/buffer.result   | 27 ++++++++++++++++++++++
 test/app/buffer.test.lua | 11 +++++++++
 7 files changed, 123 insertions(+), 54 deletions(-)

diff --git a/src/lua/buffer.lua b/src/lua/buffer.lua
index 5e9209387..7fd9f46ed 100644
--- a/src/lua/buffer.lua
+++ b/src/lua/buffer.lua
@@ -36,6 +36,34 @@ ibuf_reserve_slow(struct ibuf *ibuf, size_t size);
 
 void *
 lua_static_aligned_alloc(size_t size, size_t alignment);
+
+/**
+ * Scalar is a buffer to use with FFI functions, which usually
+ * operate with pointers to scalar values like int, char, size_t,
+ * void *. To avoid doing 'ffi.new(<type>[1])' on each such FFI
+ * function invocation, a module can use one of attributes of the
+ * scalar union.
+ *
+ * Naming policy of the attributes is easy to remember:
+ * 'a' for array type + type name first letters + 'p' for pointer.
+ *
+ * For example:
+ * - int[1] - <a>rray of <i>nt - ai;
+ * - const unsigned char *[1] -
+ *       <a>rray of <c>onst <u>nsigned <c>har <p> pointer - acucp.
+ */
+union scalar {
+    size_t as[1];
+    void *ap[1];
+    int ai[1];
+    char ac[1];
+    const unsigned char *acucp[1];
+    unsigned long aul[1];
+    uint16_t u16;
+    uint32_t u32;
+    uint64_t u64;
+    int64_t i64;
+};
 ]]
 
 local builtin = ffi.C
@@ -196,9 +224,19 @@ local function static_alloc(type, size)
     return ffi.new(type..'[?]', size)
 end
 
+--
+-- Sometimes it is wanted to use several temporary scalar cdata
+-- values. Then one union object is not enough - its attributes
+-- share memory.
+--
+local scalar_array = ffi.new('union scalar[?]', 2)
+
 return {
     ibuf = ibuf_new;
     IBUF_SHARED = ffi.C.tarantool_lua_ibuf;
     READAHEAD = READAHEAD;
     static_alloc = static_alloc,
+    scalar_array = scalar_array,
+    -- Fast access when only one variable is needed.
+    scalar = scalar_array[0],
 }
diff --git a/src/lua/crypto.lua b/src/lua/crypto.lua
index e76370517..7db6afac9 100644
--- a/src/lua/crypto.lua
+++ b/src/lua/crypto.lua
@@ -2,6 +2,7 @@
 
 local ffi = require('ffi')
 local buffer = require('buffer')
+local scalar = buffer.scalar
 
 ffi.cdef[[
     int tnt_openssl_init(void);
@@ -84,7 +85,6 @@ local function digest_new(digest)
         digest = digest,
         buf = buffer.ibuf(64),
         initialized = false,
-        outl = ffi.new('int[1]')
     }, digest_mt)
     self:init()
     return self
@@ -114,10 +114,10 @@ local function digest_final(self)
         return error('Digest not initialized')
     end
     self.initialized = false
-    if ffi.C.EVP_DigestFinal_ex(self.ctx, self.buf.wpos, self.outl) ~= 1 then
+    if ffi.C.EVP_DigestFinal_ex(self.ctx, self.buf.wpos, scalar.ai) ~= 1 then
         return error('Can\'t finalize digest: ' .. openssl_err_str())
     end
-    return ffi.string(self.buf.wpos, self.outl[0])
+    return ffi.string(self.buf.wpos, scalar.ai[0])
 end
 
 local function digest_free(self)
@@ -156,9 +156,7 @@ local function hmac_new(digest, key)
     local self = setmetatable({
         ctx = ctx,
         digest = digest,
-        buf = buffer.ibuf(64),
         initialized = false,
-        outl = ffi.new('int[1]')
     }, hmac_mt)
     self:init(key)
     return self
@@ -188,10 +186,11 @@ local function hmac_final(self)
         return error('HMAC not initialized')
     end
     self.initialized = false
-    if ffi.C.HMAC_Final(self.ctx, self.buf.wpos, self.outl) ~= 1 then
+    local buf = buffer.static_alloc('char', 64)
+    if ffi.C.HMAC_Final(self.ctx, buf, scalar.ai) ~= 1 then
         return error('Can\'t finalize HMAC: ' .. openssl_err_str())
     end
-    return ffi.string(self.buf.wpos, self.outl[0])
+    return ffi.string(buf, scalar.ai[0])
 end
 
 local function hmac_free(self)
@@ -254,7 +253,6 @@ local function cipher_new(cipher, key, iv, direction)
         direction = direction,
         buf = buffer.ibuf(),
         initialized = false,
-        outl = ffi.new('int[1]')
     }, cipher_mt)
     self:init(key, iv)
     return self
@@ -279,10 +277,10 @@ local function cipher_update(self, input)
         error("Usage: cipher:update(string)")
     end
     local wpos = self.buf:reserve(input:len() + self.block_size - 1)
-    if ffi.C.EVP_CipherUpdate(self.ctx, wpos, self.outl, input, input:len()) ~= 1 then
+    if ffi.C.EVP_CipherUpdate(self.ctx, wpos, scalar.ai, input, input:len()) ~= 1 then
         return error('Can\'t update cipher:' .. openssl_err_str())
     end
-    return ffi.string(wpos, self.outl[0])
+    return ffi.string(wpos, scalar.ai[0])
 end
 
 local function cipher_final(self)
@@ -291,11 +289,11 @@ local function cipher_final(self)
     end
     self.initialized = false
     local wpos = self.buf:reserve(self.block_size - 1)
-    if ffi.C.EVP_CipherFinal_ex(self.ctx, wpos, self.outl) ~= 1 then
+    if ffi.C.EVP_CipherFinal_ex(self.ctx, wpos, scalar.ai) ~= 1 then
         return error('Can\'t finalize cipher:' .. openssl_err_str())
     end
     self.initialized = false
-    return ffi.string(wpos, self.outl[0])
+    return ffi.string(wpos, scalar.ai[0])
 end
 
 local function cipher_free(self)
diff --git a/src/lua/msgpackffi.lua b/src/lua/msgpackffi.lua
index 609334cff..1e4786707 100644
--- a/src/lua/msgpackffi.lua
+++ b/src/lua/msgpackffi.lua
@@ -21,19 +21,10 @@ float
 mp_decode_float(const char **data);
 double
 mp_decode_double(const char **data);
-union tmpint {
-    uint16_t u16;
-    uint32_t u32;
-    uint64_t u64;
-};
 ]])
 
 local strict_alignment = (jit.arch == 'arm')
-
-local tmpint
-if strict_alignment then
-   tmpint = ffi.new('union tmpint[1]')
-end
+local scalar = buffer.scalar
 
 local function bswap_u16(num)
     return bit.rshift(bit.bswap(tonumber(num)), 16)
@@ -70,10 +61,10 @@ end
 local encode_u16
 if strict_alignment then
     encode_u16 = function(buf, code, num)
-        tmpint[0].u16 = bswap_u16(num)
+        scalar.u16 = bswap_u16(num)
         local p = buf:alloc(3)
         p[0] = code
-        ffi.copy(p + 1, tmpint, 2)
+        ffi.copy(p + 1, scalar, 2)
     end
 else
     encode_u16 = function(buf, code, num)
@@ -86,11 +77,10 @@ end
 local encode_u32
 if strict_alignment then
     encode_u32 = function(buf, code, num)
-        tmpint[0].u32 =
-            ffi.cast('uint32_t', bit.bswap(tonumber(num)))
+        scalar.u32 = ffi.cast('uint32_t', bit.bswap(tonumber(num)))
         local p = buf:alloc(5)
         p[0] = code
-        ffi.copy(p + 1, tmpint, 4)
+        ffi.copy(p + 1, scalar, 4)
     end
 else
     encode_u32 = function(buf, code, num)
@@ -104,10 +94,10 @@ end
 local encode_u64
 if strict_alignment then
     encode_u64 = function(buf, code, num)
-        tmpint[0].u64 = bit.bswap(ffi.cast('uint64_t', num))
+        scalar.u64 = bit.bswap(ffi.cast('uint64_t', num))
         local p = buf:alloc(9)
         p[0] = code
-        ffi.copy(p + 1, tmpint, 8)
+        ffi.copy(p + 1, scalar, 8)
     end
 else
     encode_u64 = function(buf, code, num)
@@ -324,9 +314,9 @@ end
 local decode_u16
 if strict_alignment then
     decode_u16 = function(data)
-        ffi.copy(tmpint, data[0], 2)
+        ffi.copy(scalar, data[0], 2)
         data[0] = data[0] + 2
-        return tonumber(bswap_u16(tmpint[0].u16))
+        return tonumber(bswap_u16(scalar.u16))
     end
 else
     decode_u16 = function(data)
@@ -339,10 +329,10 @@ end
 local decode_u32
 if strict_alignment then
     decode_u32 = function(data)
-        ffi.copy(tmpint, data[0], 4)
+        ffi.copy(scalar, data[0], 4)
         data[0] = data[0] + 4
         return tonumber(
-            ffi.cast('uint32_t', bit.bswap(tonumber(tmpint[0].u32))))
+            ffi.cast('uint32_t', bit.bswap(tonumber(scalar.u32))))
     end
 else
     decode_u32 = function(data)
@@ -356,9 +346,9 @@ end
 local decode_u64
 if strict_alignment then
     decode_u64 = function(data)
-        ffi.copy(tmpint, data[0], 8);
+        ffi.copy(scalar, data[0], 8);
         data[0] = data[0] + 8
-        local num = bit.bswap(tmpint[0].u64)
+        local num = bit.bswap(scalar.u64)
         if num <= DBL_INT_MAX then
             return tonumber(num) -- return as 'number'
         end
@@ -385,8 +375,8 @@ end
 local decode_i16
 if strict_alignment then
     decode_i16 = function(data)
-        ffi.copy(tmpint, data[0], 2)
-        local num = bswap_u16(tmpint[0].u16)
+        ffi.copy(scalar, data[0], 2)
+        local num = bswap_u16(scalar.u16)
         data[0] = data[0] + 2
         -- note: this double cast is actually necessary
         return tonumber(ffi.cast('int16_t', ffi.cast('uint16_t', num)))
@@ -403,8 +393,8 @@ end
 local decode_i32
 if strict_alignment then
     decode_i32 = function(data)
-        ffi.copy(tmpint, data[0], 4)
-        local num = bit.bswap(tonumber(tmpint[0].u32))
+        ffi.copy(scalar, data[0], 4)
+        local num = bit.bswap(tonumber(scalar.u32))
         data[0] = data[0] + 4
         return num
     end
@@ -419,9 +409,9 @@ end
 local decode_i64
 if strict_alignment then
     decode_i64 = function(data)
-        ffi.copy(tmpint, data[0], 8)
+        ffi.copy(scalar, data[0], 8)
         data[0] = data[0] + 8
-        local num = bit.bswap(ffi.cast('int64_t', tmpint[0].u64))
+        local num = bit.bswap(scalar.i64)
         if num >= -DBL_INT_MAX and num <= DBL_INT_MAX then
             return tonumber(num) -- return as 'number'
         end
@@ -552,7 +542,7 @@ end
 -- element. It is significally faster on LuaJIT to use double pointer than
 -- return result, newpos.
 --
-local bufp = ffi.new('const unsigned char *[1]');
+local bufp = scalar.acucp;
 
 local function check_offset(offset, len)
     if offset == nil then
diff --git a/src/lua/socket.lua b/src/lua/socket.lua
index cbf8c0f29..1ddafee2f 100644
--- a/src/lua/socket.lua
+++ b/src/lua/socket.lua
@@ -10,6 +10,8 @@ local fiber = require('fiber')
 local fio = require('fio')
 local log = require('log')
 local buffer = require('buffer')
+local scalar = buffer.scalar
+local scalar_array = buffer.scalar_array
 local static_alloc = buffer.static_alloc
 
 local format = string.format
@@ -473,9 +475,9 @@ local function socket_setsockopt(self, level, name, value)
     end
 
     if info.type == 1 then
-        local value = ffi.new("int[1]", value)
+        scalar.ai[0] = value
         local res = ffi.C.setsockopt(fd,
-            level, info.iname, value, ffi.sizeof('int'))
+            level, info.iname, scalar.ai, ffi.sizeof('int'))
 
         if res < 0 then
             self._errno = boxerrno()
@@ -517,8 +519,10 @@ local function socket_getsockopt(self, level, name)
     self._errno = nil
 
     if info.type == 1 then
-        local value = ffi.new("int[1]", 0)
-        local len = ffi.new("size_t[1]", ffi.sizeof('int'))
+        local value = scalar_array[0].ai
+        value[0] = 0
+        local len = scalar_array[1].as
+        len[0] = ffi.sizeof('int')
         local res = ffi.C.getsockopt(fd, level, info.iname, value, len)
 
         if res < 0 then
@@ -533,8 +537,9 @@ local function socket_getsockopt(self, level, name)
     end
 
     if info.type == 2 then
-        local value = ffi.new("char[256]", { 0 })
-        local len = ffi.new("size_t[1]", 256)
+        local value = static_alloc('char', 256)
+        local len = scalar.as
+        len[0] = 256
         local res = ffi.C.getsockopt(fd, level, info.iname, value, len)
         if res < 0 then
             self._errno = boxerrno()
@@ -556,8 +561,9 @@ local function socket_linger(self, active, timeout)
     local info = internal.SO_OPT[level].SO_LINGER
     self._errno = nil
     if active == nil then
-        local value = ffi.new("linger_t[1]")
-        local len = ffi.new("size_t[1]", 2 * ffi.sizeof('int'))
+        local value = static_alloc('linger_t')
+        local len = scalar.as
+        len[0] = 2 * ffi.sizeof('linger_t')
         local res = ffi.C.getsockopt(fd, level, info.iname, value, len)
         if res < 0 then
             self._errno = boxerrno()
@@ -800,8 +806,7 @@ local function get_recv_size(self, size)
             -- them using message peek.
             local iflags = get_iflags(internal.SEND_FLAGS, {'MSG_PEEK'})
             assert(iflags ~= nil)
-            local buf = ffi.new('char[?]', 1)
-            size = tonumber(ffi.C.recv(fd, buf, 1, iflags))
+            size = tonumber(ffi.C.recv(fd, scalar.ac, 1, iflags))
             -- Prevent race condition: proceed with the case when
             -- a datagram of length > 0 has been arrived after the
             -- getsockopt call above.
diff --git a/src/lua/string.lua b/src/lua/string.lua
index bb4adfc78..6ed6be8bf 100644
--- a/src/lua/string.lua
+++ b/src/lua/string.lua
@@ -15,8 +15,8 @@ ffi.cdef[[
 ]]
 
 local c_char_ptr     = ffi.typeof('const char *')
-local strip_newstart = ffi.new("unsigned long[1]")
-local strip_newlen   = ffi.new("unsigned long[1]")
+local strip_newstart = buffer.scalar_array[0].aul
+local strip_newlen   = buffer.scalar_array[1].aul
 
 local memcmp  = ffi.C.memcmp
 local memmem  = ffi.C.memmem
diff --git a/test/app/buffer.result b/test/app/buffer.result
index e0aad9bc7..10494b812 100644
--- a/test/app/buffer.result
+++ b/test/app/buffer.result
@@ -7,6 +7,33 @@ buffer = require('buffer')
 ffi = require('ffi')
 ---
 ...
+-- Scalar.
+scalar = buffer.scalar
+---
+...
+scalar.u16 = 100
+---
+...
+u16 = ffi.new('uint16_t[1]')
+---
+...
+ffi.copy(u16, scalar, 2)
+---
+...
+u16[0]
+---
+- 100
+...
+u16[0] = 200
+---
+...
+ffi.copy(scalar, u16, 2)
+---
+...
+scalar.u16
+---
+- 200
+...
 -- Alignment.
 _ = buffer.static_alloc('char') -- This makes buffer pos unaligned.
 ---
diff --git a/test/app/buffer.test.lua b/test/app/buffer.test.lua
index ba7299f33..6b1a974ca 100644
--- a/test/app/buffer.test.lua
+++ b/test/app/buffer.test.lua
@@ -2,6 +2,17 @@ test_run = require('test_run').new()
 buffer = require('buffer')
 ffi = require('ffi')
 
+-- Scalar.
+scalar = buffer.scalar
+scalar.u16 = 100
+u16 = ffi.new('uint16_t[1]')
+ffi.copy(u16, scalar, 2)
+u16[0]
+
+u16[0] = 200
+ffi.copy(scalar, u16, 2)
+scalar.u16
+
 -- Alignment.
 _ = buffer.static_alloc('char') -- This makes buffer pos unaligned.
 p = buffer.static_alloc('int')
-- 
2.20.1 (Apple Git-117)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [PATCH v2 1/2] buffer: port static allocator to Lua
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 1/2] " Vladislav Shpilevoy
@ 2019-05-20  9:06   ` Konstantin Osipov
  0 siblings, 0 replies; 7+ messages in thread
From: Konstantin Osipov @ 2019-05-20  9:06 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

* Vladislav Shpilevoy <v.shpilevoy@tarantool.org> [19/05/19 01:15]:
> Static allocator gives memory blocks from cyclic BSS memory
> block of 3 pages 4096 bytes each. It is much faster than
> malloc, when a temporary buffer is needed.
> 
> This commit exposes the allocator to Lua, which suffers from
> lack of ability to pass values by pointers into FFI functions,
> nor has a stack to allocate small buffers like 'char[256]'.
> Also these allocations complicate and slow down GC job.
> 
> Static allocator solves most of these problems provindg a way to
> swiftly allocate temporary memory blocks.
> 
> A simple micro benchmark showed, that ffi.new() vs
> buffer.static_alloc() is ~100 times slower, even on small
> allocations of 1Kb, and ~1.5 times slower on tiny allocations
> of 10 bytes. The results do not account GC. It is remarkable,
> buffer.static_alloc() speed does not depend on size, while
> ffi.new() strongly depends.

LGTM.


-- 
Konstantin Osipov, Moscow, Russia, +7 903 626 22 32

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union Vladislav Shpilevoy
@ 2019-05-20 14:59   ` Vladislav Shpilevoy
  2019-05-20 15:26     ` Konstantin Osipov
  0 siblings, 1 reply; 7+ messages in thread
From: Vladislav Shpilevoy @ 2019-05-20 14:59 UTC (permalink / raw)
  To: tarantool-patches; +Cc: kostja

Kostja asked to replace buffer.scalar_array and buffer.scalar
with buffer.reg1 and buffer.reg2. I did:

diff --git a/src/lua/buffer.lua b/src/lua/buffer.lua
index 7fd9f46ed..7467cb938 100644
--- a/src/lua/buffer.lua
+++ b/src/lua/buffer.lua
@@ -38,11 +38,11 @@ void *
 lua_static_aligned_alloc(size_t size, size_t alignment);
 
 /**
- * Scalar is a buffer to use with FFI functions, which usually
+ * Register is a buffer to use with FFI functions, which usually
  * operate with pointers to scalar values like int, char, size_t,
  * void *. To avoid doing 'ffi.new(<type>[1])' on each such FFI
  * function invocation, a module can use one of attributes of the
- * scalar union.
+ * register union.
  *
  * Naming policy of the attributes is easy to remember:
  * 'a' for array type + type name first letters + 'p' for pointer.
@@ -52,7 +52,7 @@ lua_static_aligned_alloc(size_t size, size_t alignment);
  * - const unsigned char *[1] -
  *       <a>rray of <c>onst <u>nsigned <c>har <p> pointer - acucp.
  */
-union scalar {
+union c_register {
     size_t as[1];
     void *ap[1];
     int ai[1];
@@ -225,18 +225,20 @@ local function static_alloc(type, size)
 end
 
 --
--- Sometimes it is wanted to use several temporary scalar cdata
--- values. Then one union object is not enough - its attributes
--- share memory.
+-- Sometimes it is wanted to use several temporary registers at
+-- once. For example, when a C function takes 2 C pointers. Then
+-- one register is not enough - its attributes share memory. Note,
+-- registers are not allocated with separate ffi.new calls
+-- deliberately. With a single allocation they fit into 1 cache
+-- line, and reduce the heap fragmentation.
 --
-local scalar_array = ffi.new('union scalar[?]', 2)
+local reg_array = ffi.new('union c_register[?]', 2)
 
 return {
     ibuf = ibuf_new;
     IBUF_SHARED = ffi.C.tarantool_lua_ibuf;
     READAHEAD = READAHEAD;
     static_alloc = static_alloc,
-    scalar_array = scalar_array,
-    -- Fast access when only one variable is needed.
-    scalar = scalar_array[0],
+    reg1 = reg_array[0],
+    reg2 = reg_array[1]
 }
diff --git a/src/lua/crypto.lua b/src/lua/crypto.lua
index 32107c0ce..d23ba8e3a 100644
--- a/src/lua/crypto.lua
+++ b/src/lua/crypto.lua
@@ -2,7 +2,7 @@
 
 local ffi = require('ffi')
 local buffer = require('buffer')
-local scalar = buffer.scalar
+local reg = buffer.reg1
 
 ffi.cdef[[
     /* from openssl/err.h */
@@ -132,10 +132,10 @@ local function digest_final(self)
         return error('Digest not initialized')
     end
     self.initialized = false
-    if ffi.C.EVP_DigestFinal_ex(self.ctx, self.buf.wpos, scalar.ai) ~= 1 then
+    if ffi.C.EVP_DigestFinal_ex(self.ctx, self.buf.wpos, reg.ai) ~= 1 then
         return error('Can\'t finalize digest: ' .. openssl_err_str())
     end
-    return ffi.string(self.buf.wpos, scalar.ai[0])
+    return ffi.string(self.buf.wpos, reg.ai[0])
 end
 
 local function digest_free(self)
@@ -205,10 +205,10 @@ local function hmac_final(self)
     end
     self.initialized = false
     local buf = buffer.static_alloc('char', 64)
-    if ffi.C.HMAC_Final(self.ctx, buf, scalar.ai) ~= 1 then
+    if ffi.C.HMAC_Final(self.ctx, buf, reg.ai) ~= 1 then
         return error('Can\'t finalize HMAC: ' .. openssl_err_str())
     end
-    return ffi.string(buf, scalar.ai[0])
+    return ffi.string(buf, reg.ai[0])
 end
 
 local function hmac_free(self)
diff --git a/src/lua/msgpackffi.lua b/src/lua/msgpackffi.lua
index 1e4786707..bfeedbc4b 100644
--- a/src/lua/msgpackffi.lua
+++ b/src/lua/msgpackffi.lua
@@ -24,7 +24,7 @@ mp_decode_double(const char **data);
 ]])
 
 local strict_alignment = (jit.arch == 'arm')
-local scalar = buffer.scalar
+local reg = buffer.reg1
 
 local function bswap_u16(num)
     return bit.rshift(bit.bswap(tonumber(num)), 16)
@@ -61,10 +61,10 @@ end
 local encode_u16
 if strict_alignment then
     encode_u16 = function(buf, code, num)
-        scalar.u16 = bswap_u16(num)
+        reg.u16 = bswap_u16(num)
         local p = buf:alloc(3)
         p[0] = code
-        ffi.copy(p + 1, scalar, 2)
+        ffi.copy(p + 1, reg, 2)
     end
 else
     encode_u16 = function(buf, code, num)
@@ -77,10 +77,10 @@ end
 local encode_u32
 if strict_alignment then
     encode_u32 = function(buf, code, num)
-        scalar.u32 = ffi.cast('uint32_t', bit.bswap(tonumber(num)))
+        reg.u32 = ffi.cast('uint32_t', bit.bswap(tonumber(num)))
         local p = buf:alloc(5)
         p[0] = code
-        ffi.copy(p + 1, scalar, 4)
+        ffi.copy(p + 1, reg, 4)
     end
 else
     encode_u32 = function(buf, code, num)
@@ -94,10 +94,10 @@ end
 local encode_u64
 if strict_alignment then
     encode_u64 = function(buf, code, num)
-        scalar.u64 = bit.bswap(ffi.cast('uint64_t', num))
+        reg.u64 = bit.bswap(ffi.cast('uint64_t', num))
         local p = buf:alloc(9)
         p[0] = code
-        ffi.copy(p + 1, scalar, 8)
+        ffi.copy(p + 1, reg, 8)
     end
 else
     encode_u64 = function(buf, code, num)
@@ -314,9 +314,9 @@ end
 local decode_u16
 if strict_alignment then
     decode_u16 = function(data)
-        ffi.copy(scalar, data[0], 2)
+        ffi.copy(reg, data[0], 2)
         data[0] = data[0] + 2
-        return tonumber(bswap_u16(scalar.u16))
+        return tonumber(bswap_u16(reg.u16))
     end
 else
     decode_u16 = function(data)
@@ -329,10 +329,10 @@ end
 local decode_u32
 if strict_alignment then
     decode_u32 = function(data)
-        ffi.copy(scalar, data[0], 4)
+        ffi.copy(reg, data[0], 4)
         data[0] = data[0] + 4
         return tonumber(
-            ffi.cast('uint32_t', bit.bswap(tonumber(scalar.u32))))
+            ffi.cast('uint32_t', bit.bswap(tonumber(reg.u32))))
     end
 else
     decode_u32 = function(data)
@@ -346,9 +346,9 @@ end
 local decode_u64
 if strict_alignment then
     decode_u64 = function(data)
-        ffi.copy(scalar, data[0], 8);
+        ffi.copy(reg, data[0], 8);
         data[0] = data[0] + 8
-        local num = bit.bswap(scalar.u64)
+        local num = bit.bswap(reg.u64)
         if num <= DBL_INT_MAX then
             return tonumber(num) -- return as 'number'
         end
@@ -375,8 +375,8 @@ end
 local decode_i16
 if strict_alignment then
     decode_i16 = function(data)
-        ffi.copy(scalar, data[0], 2)
-        local num = bswap_u16(scalar.u16)
+        ffi.copy(reg, data[0], 2)
+        local num = bswap_u16(reg.u16)
         data[0] = data[0] + 2
         -- note: this double cast is actually necessary
         return tonumber(ffi.cast('int16_t', ffi.cast('uint16_t', num)))
@@ -393,8 +393,8 @@ end
 local decode_i32
 if strict_alignment then
     decode_i32 = function(data)
-        ffi.copy(scalar, data[0], 4)
-        local num = bit.bswap(tonumber(scalar.u32))
+        ffi.copy(reg, data[0], 4)
+        local num = bit.bswap(tonumber(reg.u32))
         data[0] = data[0] + 4
         return num
     end
@@ -409,9 +409,9 @@ end
 local decode_i64
 if strict_alignment then
     decode_i64 = function(data)
-        ffi.copy(scalar, data[0], 8)
+        ffi.copy(reg, data[0], 8)
         data[0] = data[0] + 8
-        local num = bit.bswap(scalar.i64)
+        local num = bit.bswap(reg.i64)
         if num >= -DBL_INT_MAX and num <= DBL_INT_MAX then
             return tonumber(num) -- return as 'number'
         end
@@ -542,7 +542,7 @@ end
 -- element. It is significally faster on LuaJIT to use double pointer than
 -- return result, newpos.
 --
-local bufp = scalar.acucp;
+local bufp = reg.acucp;
 
 local function check_offset(offset, len)
     if offset == nil then
diff --git a/src/lua/socket.lua b/src/lua/socket.lua
index 1ddafee2f..ad894c0fb 100644
--- a/src/lua/socket.lua
+++ b/src/lua/socket.lua
@@ -10,8 +10,8 @@ local fiber = require('fiber')
 local fio = require('fio')
 local log = require('log')
 local buffer = require('buffer')
-local scalar = buffer.scalar
-local scalar_array = buffer.scalar_array
+local reg1 = buffer.reg1
+local reg2 = buffer.reg2
 local static_alloc = buffer.static_alloc
 
 local format = string.format
@@ -475,9 +475,9 @@ local function socket_setsockopt(self, level, name, value)
     end
 
     if info.type == 1 then
-        scalar.ai[0] = value
+        reg1.ai[0] = value
         local res = ffi.C.setsockopt(fd,
-            level, info.iname, scalar.ai, ffi.sizeof('int'))
+            level, info.iname, reg1.ai, ffi.sizeof('int'))
 
         if res < 0 then
             self._errno = boxerrno()
@@ -519,9 +519,9 @@ local function socket_getsockopt(self, level, name)
     self._errno = nil
 
     if info.type == 1 then
-        local value = scalar_array[0].ai
+        local value = reg1.ai
         value[0] = 0
-        local len = scalar_array[1].as
+        local len = reg2.as
         len[0] = ffi.sizeof('int')
         local res = ffi.C.getsockopt(fd, level, info.iname, value, len)
 
@@ -538,7 +538,7 @@ local function socket_getsockopt(self, level, name)
 
     if info.type == 2 then
         local value = static_alloc('char', 256)
-        local len = scalar.as
+        local len = reg1.as
         len[0] = 256
         local res = ffi.C.getsockopt(fd, level, info.iname, value, len)
         if res < 0 then
@@ -562,8 +562,8 @@ local function socket_linger(self, active, timeout)
     self._errno = nil
     if active == nil then
         local value = static_alloc('linger_t')
-        local len = scalar.as
-        len[0] = 2 * ffi.sizeof('linger_t')
+        local len = reg1.as
+        len[0] = ffi.sizeof('linger_t')
         local res = ffi.C.getsockopt(fd, level, info.iname, value, len)
         if res < 0 then
             self._errno = boxerrno()
@@ -806,7 +806,7 @@ local function get_recv_size(self, size)
             -- them using message peek.
             local iflags = get_iflags(internal.SEND_FLAGS, {'MSG_PEEK'})
             assert(iflags ~= nil)
-            size = tonumber(ffi.C.recv(fd, scalar.ac, 1, iflags))
+            size = tonumber(ffi.C.recv(fd, reg1.ac, 1, iflags))
             -- Prevent race condition: proceed with the case when
             -- a datagram of length > 0 has been arrived after the
             -- getsockopt call above.
diff --git a/src/lua/string.lua b/src/lua/string.lua
index 6ed6be8bf..6e12c59ae 100644
--- a/src/lua/string.lua
+++ b/src/lua/string.lua
@@ -15,8 +15,8 @@ ffi.cdef[[
 ]]
 
 local c_char_ptr     = ffi.typeof('const char *')
-local strip_newstart = buffer.scalar_array[0].aul
-local strip_newlen   = buffer.scalar_array[1].aul
+local strip_newstart = buffer.reg1.aul
+local strip_newlen   = buffer.reg2.aul
 
 local memcmp  = ffi.C.memcmp
 local memmem  = ffi.C.memmem
diff --git a/test/app/buffer.result b/test/app/buffer.result
index 10494b812..beccc5a87 100644
--- a/test/app/buffer.result
+++ b/test/app/buffer.result
@@ -7,17 +7,17 @@ buffer = require('buffer')
 ffi = require('ffi')
 ---
 ...
--- Scalar.
-scalar = buffer.scalar
+-- Registers.
+reg1 = buffer.reg1
 ---
 ...
-scalar.u16 = 100
+reg1.u16 = 100
 ---
 ...
 u16 = ffi.new('uint16_t[1]')
 ---
 ...
-ffi.copy(u16, scalar, 2)
+ffi.copy(u16, reg1, 2)
 ---
 ...
 u16[0]
@@ -27,10 +27,10 @@ u16[0]
 u16[0] = 200
 ---
 ...
-ffi.copy(scalar, u16, 2)
+ffi.copy(reg1, u16, 2)
 ---
 ...
-scalar.u16
+reg1.u16
 ---
 - 200
 ...
diff --git a/test/app/buffer.test.lua b/test/app/buffer.test.lua
index 6b1a974ca..a1c380680 100644
--- a/test/app/buffer.test.lua
+++ b/test/app/buffer.test.lua
@@ -2,16 +2,16 @@ test_run = require('test_run').new()
 buffer = require('buffer')
 ffi = require('ffi')
 
--- Scalar.
-scalar = buffer.scalar
-scalar.u16 = 100
+-- Registers.
+reg1 = buffer.reg1
+reg1.u16 = 100
 u16 = ffi.new('uint16_t[1]')
-ffi.copy(u16, scalar, 2)
+ffi.copy(u16, reg1, 2)
 u16[0]
 
 u16[0] = 200
-ffi.copy(scalar, u16, 2)
-scalar.u16
+ffi.copy(reg1, u16, 2)
+reg1.u16
 
 -- Alignment.
 _ = buffer.static_alloc('char') -- This makes buffer pos unaligned.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union
  2019-05-20 14:59   ` [tarantool-patches] " Vladislav Shpilevoy
@ 2019-05-20 15:26     ` Konstantin Osipov
  0 siblings, 0 replies; 7+ messages in thread
From: Konstantin Osipov @ 2019-05-20 15:26 UTC (permalink / raw)
  To: tarantool-patches

* Vladislav Shpilevoy <v.shpilevoy@tarantool.org> [19/05/20 18:01]:
> Kostja asked to replace buffer.scalar_array and buffer.scalar
> with buffer.reg1 and buffer.reg2. I did:

lgtm. 



-- 
Konstantin Osipov, Moscow, Russia, +7 903 626 22 32

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [PATCH v2 0/2] buffer: port static allocator to Lua
  2019-05-18 22:15 [tarantool-patches] [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 1/2] " Vladislav Shpilevoy
  2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union Vladislav Shpilevoy
@ 2019-05-21 16:56 ` Vladislav Shpilevoy
  2 siblings, 0 replies; 7+ messages in thread
From: Vladislav Shpilevoy @ 2019-05-21 16:56 UTC (permalink / raw)
  To: tarantool-patches; +Cc: kostja

Pushed to the master.

On 19/05/2019 01:15, Vladislav Shpilevoy wrote:
> The patchset allows to use the static allocator from Lua, and optimizes some
> commonly appearing problems with passing parameters into FFI functions by a
> pointer.
> 
> Changes in V2:
> - Split in 2 commits.
> 
> V1: https://www.freelists.org/post/tarantool-patches/PATCH-11-buffer-port-static-allocator-to-Lua
> 
> Branch: http://github.com/tarantool/tarantool/tree/gerold103/static-allocator-lua
> 
> Vladislav Shpilevoy (2):
>   buffer: port static allocator to Lua
>   buffer: replace all ffi.new(type[1]) with cached union
> 
>  extra/exports            |  2 ++
>  src/CMakeLists.txt       |  1 +
>  src/box/lua/schema.lua   |  3 +-
>  src/lua/buffer.c         | 42 +++++++++++++++++++++++++++
>  src/lua/buffer.lua       | 61 ++++++++++++++++++++++++++++++++++++++++
>  src/lua/crypto.lua       | 22 +++++++--------
>  src/lua/digest.lua       |  7 +++--
>  src/lua/fio.lua          |  3 +-
>  src/lua/init.c           |  2 +-
>  src/lua/msgpackffi.lua   | 50 +++++++++++++-------------------
>  src/lua/socket.lua       | 36 ++++++++++++++----------
>  src/lua/string.lua       | 10 ++++---
>  src/lua/uri.lua          |  7 +++--
>  src/lua/uuid.lua         |  9 +++---
>  test/app/buffer.result   | 53 ++++++++++++++++++++++++++++++++++
>  test/app/buffer.test.lua | 23 +++++++++++++++
>  16 files changed, 256 insertions(+), 75 deletions(-)
>  create mode 100644 src/lua/buffer.c
>  create mode 100644 test/app/buffer.result
>  create mode 100644 test/app/buffer.test.lua
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-05-21 16:56 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-18 22:15 [tarantool-patches] [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy
2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 1/2] " Vladislav Shpilevoy
2019-05-20  9:06   ` [tarantool-patches] " Konstantin Osipov
2019-05-18 22:15 ` [tarantool-patches] [PATCH v2 2/2] buffer: replace all ffi.new(type[1]) with cached union Vladislav Shpilevoy
2019-05-20 14:59   ` [tarantool-patches] " Vladislav Shpilevoy
2019-05-20 15:26     ` Konstantin Osipov
2019-05-21 16:56 ` [tarantool-patches] Re: [PATCH v2 0/2] buffer: port static allocator to Lua Vladislav Shpilevoy

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