<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[QUIK -> DDE &mdash; Qlua + luajit]]></title>
		<link>https://quik2dde.ru/viewtopic.php?id=292</link>
		<atom:link href="https://quik2dde.ru/extern.php?action=feed&amp;tid=292&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «Qlua + luajit».]]></description>
		<lastBuildDate>Thu, 16 May 2019 06:50:09 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Qlua + luajit]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2363#p2363</link>
			<description><![CDATA[<p>Что касается luajit - то проблема в многопоточности и наличии main().<br />Как это решили в QUIKSharp - я не смотрел.</p><p>Если я всё верно понял, то программы, использующие QUIKSharp, запускаются отдельным процессом, внешним по отношению к QUIK. Что как раз позволяет свободно использовать любой функционал, в том числе создание пользовательского интерфейса.<br />Но могу ошибаться, хорошо бы уточнить.</p><p>Конечно в идеале было бы правильно просто встроить luajit в QUIK для ускорения работы роботов, это было бы логично.<br />Ну а дальше уже начинается вкусовщина. Я лично не очень понимаю зачем писать на разных питонах/C# и далее по списку, когда предлагается Lua. Роботы-то от этого не начинают лучше работать )<br />Другое дело, если эти внешние средства предоставляют новое возможности. Но вот какие - я не очень понимаю.</p>]]></description>
			<author><![CDATA[null@example.com (swerg)]]></author>
			<pubDate>Thu, 16 May 2019 06:50:09 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2363#p2363</guid>
		</item>
		<item>
			<title><![CDATA[Re: Qlua + luajit]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2361#p2361</link>
			<description><![CDATA[<p>Нашел подобный проект [url]https://github.com/Enfernuz/quik-lua-rpc[/url]<br />Там используется ZeroMQ и Protocol Buffers.<br />Странно, что не видел его раньше, хотя целенаправленно искал полгода назад lua rpc библиотеки.</p><p>И сегодня вышел QUIKSharp ver 1.0, цель проекта: «повторить API QLUA в C# максимально точно и качественно». <br />[url]https://smart-lab.ru/blog/538825.php[/url]<br />Реализация аналогичная - передача сообщений через сокеты и json.</p><p>На мой личный вкус, luajit сравним по скорости с C#но проще и компактнее по размеру кода и рантайма.<br />Ещё интересная связка Moonscript + qlua/luajit.</p>]]></description>
			<author><![CDATA[null@example.com (reader)]]></author>
			<pubDate>Wed, 15 May 2019 20:42:15 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2361#p2361</guid>
		</item>
		<item>
			<title><![CDATA[Re: Qlua + luajit]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2359#p2359</link>
			<description><![CDATA[<p><strong>Тест tango.</strong></p><p>Сервер tango_srv.lua:<br /></p><div class="codebox"><pre><code>require&#039;tango.server.copas_socket&#039;
local random = math.random

function Frand(i)
    return random(-i,i)
end

print(&quot;start server localhost:12345&quot;)
tango.server.copas_socket.loop{
  port = 12345,
  host = &quot;*&quot;
}</code></pre></div><p>Запуск: <br /></p><div class="codebox"><pre><code>start luajit tango_srv.lua &gt;tango_srv.log</code></pre></div><p>test_tango_rpc.lua:<br /></p><div class="codebox"><pre><code>require&#039;tango.client.socket&#039;
local random = math.random
local res, time, N = 0, 0, 1000
-- 1 вычисления в цикле
-- 2 то же в функции
-- 3 то же в функции RPC

function runtest0( times)
    local begin = os.clock()
    local x=0
    for i = 1, times do
        x = x + random(-i,i)
    end
    local endtm = os.clock()
    return x, endtm - begin
end

function runtest(func, times)
    local begin = os.clock()
    local x=0
    for i = 1, times do
        x = x + func(i)
    end
    local endtm = os.clock()
    return x, endtm - begin
end

function Frand(i)
    return random(-i,i)
end

local proxy = tango.client.socket.connect{
   address = &#039;localhost&#039;,
   port = 12345
}

res,time = runtest0(N)
print(&quot;test loop&quot;, time)

res,time = runtest(Frand, N)
print(&quot;test Frand&quot;, time)

res,time = runtest(proxy.Frand,N)
print(&quot;test proxy.Frand&quot;, time)</code></pre></div><p>Запуск: </p><div class="codebox"><pre><code>luajit -joff test_tango_rpc.lua</code></pre></div><p>результат:<br /></p><div class="codebox"><pre><code>test loop    0
test Frand    0
test proxy.Frand    0.238</code></pre></div><p>0.24 ms на вызов функции через sockets.</p>]]></description>
			<author><![CDATA[null@example.com (reader)]]></author>
			<pubDate>Sat, 20 Apr 2019 10:04:19 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2359#p2359</guid>
		</item>
		<item>
			<title><![CDATA[Re: Qlua + luajit]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2358#p2358</link>
			<description><![CDATA[<p>Сравнение annotate c checks (проверка типов в dll) и прямой проверкой типов в коде.<br /></p><div class="codebox"><pre><code>-- compare checks and annotate.check
local getmetatable=getmetatable

require &#039;checks&#039;
     
-- Custom checker function --
function checkers.port(p)
  return type(p)==&#039;number&#039; and p&gt;0 and p&lt;0x10000
end

-- A new named type --
socket_mt = { __type=&#039;socket&#039;, _type=&#039;socket&#039; }
asocket = setmetatable ({ }, socket_mt)

-- Annotate
local annotate = require( &quot;annotate&quot; )
local check = require( &quot;annotate.check&quot; )
check.types.port = function( p )
  return type(p)==&#039;number&#039; and p&gt;0 and p&lt;0x10000
end

check.types.socket = function( sock )
  return (getmetatable (sock) or {})._type or type (sock)
end

-- original function
local test_func = function (n, s, t, sock, port, str)
  sock.port=port 
  if str and not sock[str] then 
     sock[str]= getmetatable(sock)
  end
  sock.n = (sock.n or 1) + 1
  return s..n
end

local function test_checks ( n, s, t, sock, port, str)
  checks (&#039;number&#039;, &#039;string&#039;, &#039;table&#039;, &#039;socket&#039;, &#039;port&#039;, &#039;?string&#039;)
  return test_func
end

local test_annotate = annotate[=[
test_annotate( n, s, t, sock, port, str ) =&gt; string
    n: number
    s: string
    t: table
    sock: socket
    port: port
    str:  nil/string
]=] .. test_func

-- my checks
local io_type=io.type
local function _type (x)
  return (getmetatable (x) or {})._type or io_type (x) or type (x)
end

-- assert - my best
local function test_mycheck(n, s, t, sock, port, str)
  if     type(n)~=&quot;number&quot;  then error(&quot;wrong param #1:&quot;..tostring(n))
  elseif type(s)~=&quot;string&quot;   then error(&quot;wrong param #2:&quot;..tostring(s))
  elseif type(t)~=&quot;table&quot;   then error(&quot;wrong param #3:&quot;..tostring(t))
  elseif not ( type( sock)==&quot;table&quot; and (getmetatable(sock) or {})._type==&quot;socket&quot; ) 
    then error(&quot;wrong param #4:&quot;..tostring(sock))
  elseif not ( type( port)==&quot;number&quot; and port&gt;0 and port&lt;0x10000) -- &quot;type&quot; port
    then error(&quot;wrong param #5:&quot;..tostring(port))
  elseif type(str)~=&quot;string&quot;   then error(&quot;wrong param #6:&quot;..tostring(str))
  end
  return test_func
end

function run_test(fname, fn, sock, port, str)
  local x=&#039;&#039;
  local t={1,2,3}
  local n=1000000
  local start_time=os.clock()

  for i=1,n do
    fn( i, &#039;dhdh&#039;, t, sock, i%10000+1, str)
  end
  print(fname, &quot;time:&quot;, tonumber(os.clock() - start_time))
end

print(&quot;------------------------------------&quot;)
run_test(&quot;pure test_func&quot;, test_func, asocket, 1024, &quot;hello&quot;)
run_test(&quot;test_checks&quot;, test_checks, asocket, 1024, &quot;hello&quot;)
run_test(&quot;test_annotate&quot;, test_annotate, asocket, 1024, &quot;hello&quot;)
run_test(&quot;test_mycheck&quot;, test_mycheck, asocket, 1024, &quot;hello&quot;)</code></pre></div><p>Результат в luajit:<br />------------------------------------<br />pure test_func&nbsp; &nbsp; time:&nbsp; &nbsp; 0.008<br />test_checks&nbsp; &nbsp; time:&nbsp; &nbsp; 0.853<br />test_annotate&nbsp; &nbsp; time:&nbsp; &nbsp; 0.009<br />test_mycheck&nbsp; &nbsp; time:&nbsp; &nbsp; 0.007</p><p>Накладные расходы 1 ms на 1 млн вызовов в pure lua - отличный результат.<br />Проверка типов через checks.dll на 2 порядка медленнее.</p>]]></description>
			<author><![CDATA[null@example.com (reader)]]></author>
			<pubDate>Sat, 20 Apr 2019 08:59:22 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2358#p2358</guid>
		</item>
		<item>
			<title><![CDATA[Qlua + luajit]]></title>
			<link>https://quik2dde.ru/viewtopic.php?pid=2357#p2357</link>
			<description><![CDATA[<p>1) Берём luajit (тестировал со сборкой Scilua/ulua, там удобный менеджер пакетов).<br />2) Для связи с quik - любая библиотека RPC (remote procedure call), как минимум достаточно socket + сериализации таблиц в строку/json. Я остановился на tango-copas ([url]http://github.com/lipp/tango[/url])<br />3) Для проверки типов аргументов функций - annotate ([url]http://siffiejoe.github.io/lua-annotate/[/url])</p><p>Схема примерно такая:</p><p> Qlua&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; luajit<br />-------------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -----------------<br />| callback&nbsp; |----------&gt;| tango server |- - - -&gt;/--------------\<br />-------------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -----------------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; SQLite&nbsp; &nbsp; &nbsp; &nbsp; |<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;^&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; &nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; database&nbsp; &nbsp; &nbsp;|<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp; <br />----------------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ----------------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| logs&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|<br />| main&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |&lt;-------| Main&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| - - - -&gt;\--------------/<br />|tango server|&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |tango server|<br />----------------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ----------------</p><br /><br /><p>Плюсы:<br />Так как luajit на порядок быстрее lua, проверка типов получается &quot;бесплатной&quot;. <br />Вообще можно всю логику перенести в luajit, по аналогии со связками qlua + C#/C++<br />Доступны все библиотеки lua, включая GUI (без танцев с бубнами вокруг dll и mainloop UI/Qlua), SQLite.<br />Доступна реальная многозадачность.<br />Можно заменить luajit на что угодно - Python, javascript, Java, C# при сохранении совместимого протокола передачи данных.<br />Можно заменить Qlua на эмулятор для тестирования и отладки.</p><p>Минусы:<br />Так как main и колбэки работают параллельно, соответствующие им процедуры на стороне luajit нужно запускать в параллельных потоках или даже в отдельных процессах. Для передачи данных между ними нужно использовать либо базу данных, либо те же sockets+json.<br />Усложняется процедура инициализации и восстановления после сбоев.</p>]]></description>
			<author><![CDATA[null@example.com (reader)]]></author>
			<pubDate>Fri, 19 Apr 2019 20:21:01 +0000</pubDate>
			<guid>https://quik2dde.ru/viewtopic.php?pid=2357#p2357</guid>
		</item>
	</channel>
</rss>
