Кривые шибки в QLua

Страницы: 1 2 След.
RSS
Кривые шибки в QLua
 
Здесь будут публиковаться кривые ошибки, возникающие, очевидно, из-за двухпоточной схемы работы QLua.
Некоторые ошибки указаны здесь: Потокобезопасные функции в Lua 5.3
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Код
local run = true
function OnAllTrade(alltrade)
end
function OnParam(class, sec)
end
function main()
  local getinfo = debug.getinfo
  while run do
    for i = 1, 100 do
      getinfo(1)
    end
    sleep(1)
  end
end
function OnStop()
  run = nil
end

Ошибка в строке getinfo(1)
Цитата
bad argument #1 to 'getinfo' (number expected, got nil)
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
Старатель написал:
Ошибка в строке getinfo(1)
Не воспроизвелось, работает себе и работает.
 
Никто и не обещал, что ошибка появляется всегда и сразу.
Можно запустить несколько копий скрипта, как тут, сделать перезаказ обезличенных сделок...
В общем, ошибка именно в этом коде и именно в этом месте присутствует. А как гарантированно воспроизвести - без понятия. Надо смотреть сорцы, откуда там nil.
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Скрипт тот же, строка та же: #2
Ошибка
Цитата
attempt to call a nil value
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Старатель, вопрос-предположение, у вас всегда параллельно со скриптами работает хоть один луа-индикатор?
 
Цитата
Anton написал:
у вас всегда параллельно со скриптами работает хоть один луа-индикатор
Если вопрос по скриптам из текущей и этой тем, то нет, в тестовом квике даже графики не открыты.
Открытые окна:
Скрытый текст
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
Старатель написал:
в тестовом квике даже графики не открыты
Ага, спасибо. Закралась было мыслЯ, но нет )
 
Давненько я кривее ошибки не видел! Лет примерно 30-35! :)

Суть дела: написал я тестовый скрипт на Lua (чтобы разобраться, что здесь как работает - с языком до этого не сталкивался вообще). Тест заработал, я скопировал код в другой файл, уже почти "боевой", что-то там подрихтовал, запускаю - НЕ работает! Я стал сравнивать оба кода - НУ ВСЁ ТОЧНО ТАК ЖЕ! Проматерившись минут 40, я локализовал, наконец, место глюка. Из серии "не верь глазам своим". Вот полный код теста:

f=true
function main()
while f do
 sleep(5000)
end
message("Скрипт остановлен!")
end

function OnStop()
f=false
end

Как оказалось, ошибка заключается в том (я миллион раз смотрел на это место!), что в "боевом" скрипте у меня стоит sleep(15000) - ну не нужно мне чаще! А эта скотина, как оказалось, через 5 секунд после останова принудительно завершает работу, "воруя" у меня управление. Читаю документацию - там стоит:
[NUMBER time_out] OnStop(NUMBER signal)
Что за "сигнал" - покрыто мраком, и в тестовых примерах никто его не использует, равно как и возвращаемое значение: флаг сбросили - что же тут возвращать? Ан нет - "Функция возвращает количество миллисекунд, которое дается скрипту на завершение работы", а по умолчанию у неё таймаут даётся именно в те самые 5 секунд! По этим словам тоже взгляд скользит, не задерживаясь - какое может быть "время для завершения", если у меня скрипт практически ничего не делает? А вот время на "безделье", на ожидание окончания последнего "sleep" - вынь, да положь! Короче, вот исправленный код, который корректно завершается даже при 15-секундной задержке:

function OnStop()
f=false
return 20000
end

УФ! Не, сейчас-то уже смешно, но тогда!..  :smile:  
 
Здравствуйте, Старатель,

Ваше сообщение получено, проблема изучается. Постараемся в ближайшее время дать ответ.
 
QUIK v.8.11.0.66, Lua 5.4
Однократная ошибка
Цитата
attempt to call a nil value
в цикле for in pairs в main:
Код
local T = {}

function main()

    while run do
      ...
        for k, v in pairs(T) do  -- тут ошибка
          ...
        end
      ...
      sleep(1)
    end

end
stack traceback:
Цитата
in for iterator 'for iterator'

На момент возникновения ошибки таблица T была пуста: за время работы (3 часа) робота в таблицу элементы не добавлялись.
Написать тестовый скрипт для воспроизведения или повторить ошибку не удалось.
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Старатель, добрый день!

Цитата
Старатель написал:
Код
   local  run  =   true 
 function   OnAllTrade (alltrade)
 end 
 function   OnParam (class, sec)
 end 
 function   main ()
   local  getinfo  =  debug.getinfo
   while  run  do 
     for  i  =   1 ,  100   do 
      getinfo( 1 )
     end 
     sleep ( 1 )
   end 
 end 
 function   OnStop ()
  run  =   nil 
 end   

Ошибка в строке  getinfo(1)
Цитата
bad argument #1 to 'getinfo' (number expected, got nil)
К сожалению, нам не удалось понять причину проблемы. Рекомендуем использовать терминал версии 8.11 и Lua 5.4.
Приносим извинения за причинённые неудобства.

Касательно последнего сообщения, ответим немного позже.
 
Цитата
Старатель написал:
QUIK v.8.11.0.66, Lua 5.4
Однократная ошибка
Цитата
attempt to call a nil value
в цикле for in pairs в main:
Код
   local  T  =  {}

 function   main ()

     while  run  do 
       .. .
         for  k, v  in  pairs(T)  do    -- тут ошибка 
           .. .
         end 
       .. .
       sleep ( 1 )
     end 

 end   
stack traceback:
Цитата
in for iterator 'for iterator'

На момент возникновения ошибки таблица T была пуста: за время работы (3 часа) робота в таблицу элементы не добавлялись.
Написать тестовый скрипт для воспроизведения или повторить ошибку не удалось.
Проблема изучается. Постараемся в ближайшее время дать ответ.
 
Здравствуйте, Старатель.

К сожалению нам не удалось понять причину возникновения описанной ошибки.
Приносим извинения за причиненные неудобства.
 
В инструкции написано о довольно странной многопоточности. Действительно ли то, что многопоточность реализована путём патча виртуальной машины Lua в котором треды  в любой момент времени могут очистить стек виртуальной машины и заполнить другими данными для начала исполнение колбека? Если это так, и если момент перехвата управления точно совпадает с моментом передачи аргументов в функцию, то возможна потеря аргументов если стек не был восстановлен корректно при завершении работы колбека.

Старатель, попробуйте запустить этот же код без колбеков.
 
Артем, добрый день!

Никакого патча виртуальной машины Lua не выполнялось.
Вся многопоточность реализована исключительно нативными средствами самого Lua.
 
Roman Azarov, Lua принципиально не поддерживает многопоточность, нативных средств реализации нет. В силу чего многопоточность Lua реализуют запуском отдельной виртуальной машины на каждый тред, и реализацией отправки данных между виртуальными машинами через C++, и вам тоже советую использовать такой-же метод. Один из простых методов реализации колбеков в однопоточном Lua заключается в том, чтобы писать колбеки в стек и сделать так, чтобы функция sleep вызывала колбеки и только после этого останавливала выполнение на оставшееся количество времени. Реализовывать можно прямо в Lua а не в C++.


Код
function sleep(ms)
  local t1 = os.clock()
  for cb, ... in _cplusplus_pollCallbacks() do
    if type(_G[cb]) == 'function' then cb(...) end 
  end
  _cpusplus_sleep(math.max(0, (os.clock() - t1) * 1000 - ms))
end 

У вас тут повреждение стека виртуальной машины в случайные моменты времени, налицо наличие каких-то неочевидных ошибок в реализации многопоточности, и врядли у вас в команде есть программист С++ у которого IQ выше 180 чтобы этот баг можно было отловить и починить. Надо признать что интеллект до уровня Богов Олимпа всё-таки не дотягивает и решать проблему методами, которые под силу простому человеку.
 
Код
if type(_G[cb]) == 'function' then _cplusplus_callbackReturn(cb, cb(...)) end 
 
Артем, Многопоточность достаточно тривиально реализуется на ЛЮБОМ языке - это разновидность программирования данными. Многопроцессность - с этим значительно сложнее, но тоже нет ничего "принципиально не поддерживаемого". Ну, а если "запускать отдельную виртуальную машину на каждый тред", то дурное дело нехитрое. А какой простор для труднонаходимых глюков!..  :smile:

Оставьте хоть sleep в покое - чуть ли не единственное осталось, что пока работает!
 
Владимир, как товарищ Эйнштейн завещал: в теории, теория и практика это одно и тоже, но на практике, практика и теория сильно различаются. Так что то, что способ хорошо реализовать многопроцессность на Lua существует, еще не значит что кто-то его сможет найти в обозримом будущем. Ни один интерпретируемый язык не поддерживает работу на нескольких физических процессорах и изменения на этом фронте не предвидятся.
 
Артем, А при чём тут "работа на нескольких физических процессорах"? И одного вполне достаточно! Нет, "в обозримом будущем" действительно никто ничего не найдёт, я мало сомневаюсь. А вот "в обозримом прошлом" это особых проблем не составляло. Тоже мне бином Ньютона!(с) В частности, я сам делал нечно подобное на JS. А описание "нормального" монитора (сишного) приведено у меня в книге. Фрагмент:

Идея монитора довольно проста – он обслуживает процесс, то есть набор управляющих данных, представленных в виде стека очередей. Новая группа (объектов или событий) просто заносится как очередь (LIFO) на вершину стека (FIFO), т.е. очередь на вершине стека – это самые приоритетные на данный момент данные, которые обслуживаются по своей очереди «вне очереди». Ниже по стеку расположены те очереди, которые не будут обслужены до обработки всех верхних очередей стека. Собственно, именно так работает любой процессор: обслуживание текущей очереди определяется регистром счётчика команд, а выполнение вложенных процедур – регистром указателя стека. Для доступа к возвращаемым значениям методов используется стек аккумуляторов, устроенный аналогично стеку регистров сопроцессора, для неоднородных объектов – специальный стек системного уровня. Очередное событие из стека очередей обслуживается текущим обработчиком. Размер стека составляет обычно 64 очереди.

И далее:

У нас пока не возникало необходимости программирования многозадачных приложений, хотя техническая возможность создания нескольких процессов в рамках одного приложения имеется, и даже не очень сложна в реализации. Следует лишь помнить, что методы класса функции работают на одном и том же программном стеке, и при переключении процессов следует заботиться о сохранении и восстановлении данных этого стека.
 
Напоминаю, что каждое "ядро" это отдельный физический процессор. В домашних компьютерах как правило имеется всего 1 сокет и все процессоры монтируются на одном куске кремния, так что принято думать будто плата, на которой смонтировано десяток процессоров, это монолитный "процессор", а "ядра" это так, эфемерное понятие. На рабочих станциях и серверах распространены платы с 2, 4 и более сокетами под процессоры, и каждый процессор зачастую состоит из нескольких раздельных чипов, это проливает некоторый свет на идею многоядерности.


Владимир, не вижу связи с предметом разговора. Специально описывается система, которая работает последовательно на одном процессоре, без какой-либо параллельности. А у нас тут наоборот, проблема в том, что люди пытаются натянуть сову на глобус и заставить однопоточный Lua работать сразу на несколько процессоров, с ожидаемым результатом (вылеты скриптов на пустом месте).
 
Артем, Спасибо,я в курсе,что "каждое ядро это отдельный физический процессор". Представьте, что на компьютере один ОДНОЯДЕРНЫЙ процессор. Это ничуть не мешает организовать многопроцессную работу - примерно так, как я описал выше.

Не знаю, каким образом "люди пытаются натянуть сову на глобус и заставить однопоточный Lua работать сразу на несколько процессоров" (с их-то несчастными возможностями тупого интерпретируемого кода), но с "вылетами скриптов на пустом месте" я разобрался - больше не вылетает, исправил все свои ошибки и обвистовал чужие. А вот вылет самого Квика на ровном месте встречается всё чаще: несколько часов назад рухнул и сегодня у одного из брокеров (у которого версия 8.11 - у второго версия 8.8 работает уже несколько месяцев без нареканий). И эта тенденция мне СОВСЕМ не нравится! Кстати, этот брокер порекомендовал мне перейти на новую версию, которая оказалась 8.13, и началось такое, что торги вообще пришлось остановить! Завтра буду разбираться с брокером.
 
QUIK v.8.13.0.106, Lua 5.4

Очередная ошибка
Цитата
attempt to call a nil value (method 'pop')
Скрипт:
Скрытый текст
Queue работает годами в разных скриптах. И (условно) раз в год (или реже) скрипты ругаются на nil. Было в 7-й или 6-й версии квика. Какое тогда было сообщение об ошибке не помню.

Скрытый текст
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Старатель, добрый день!

Проблема с ошибкой "attempt to call a nil value (method 'pop')" изучается. Постараемся в ближайшее время дать ответ.

Проблему с code highlighter также приняли во внимание.
Касательно нее ответим позднее.
 
Старатель, добрый день!

Проблему с code highlighter починили, можете проверять.
 
Цитата
Старатель написал:
QUIK v.8.13.0.106, Lua 5.4

Очередная ошибка
Цитата
attempt to call a nil value (method 'pop')
Скрипт:
    Скрытый текст        
Код
  Queue  =  {
  new  =   function  (self)
     return  setmetatable({first  =   1 , last  =   0 }, {__index  =  self})
   end ,
  push  =   function  (self, v)
     local  last  =  self.last  +   1 
    self[last]  =  v
    self.last  =  last
     return  last
   end ,
  pop  =   function  (self)
     local  first  =  self.first
     if  first  >  self.last  then   return   nil   end 
     local  v  =  self[first]
    self.first  =  first  +   1 
    self[first]  =   nil 
     return  v
   end ,
  size  =   function  (self)
     return  self.last  -  self.first  +   1 
   end 
}

 local  OnAllTra des  =  Queue:new()
 local   function  f(alltrade)
   .. .
  OnAllTrades:push(alltrade)
   .. .
 end 

 function   OnAllTrade (alltrade)
   .. .   -- Во время ошибки параллельный поток находился где-то здесь 
  f(alltrade)
 end 

 local  run  =   true 
 function   main ()
   while  run  do 
     .. .
     if  OnAllTrades:size()  >   0   then 
      local  alltrade  =  OnAllTrades:pop()   -- Тут ошибка "attempt to call a nil value (method 'pop')" 
      .. .
     end 
   end 
 end   
Queue работает годами в разных скриптах. И (условно) раз в год (или реже) скрипты ругаются на nil. Было в 7-й или 6-й версии квика. Какое тогда было сообщение об ошибке не помню.

    Скрытый текст       И ещё претензия к code highlighter на форуме: в строке 24
Код
   local  OnAllTra des  =  Queue:new()  
он зачем-то добавляет пробел внутри слова
Добрый день,
     
      Действительно, в ПО QLUA есть ошибка функций обратного вызова       скрипта приводящая к подобным ошибкам. Мы справим её в очередном       обновлении ПО приносим извинения за причинённые неудобства.
 
QUIK 9.1.0.63, Lua 5.4
Сегодня в коде (в main)
Код
local hour = 0+os.date('%H')
выскочила такая ошибка:
Цитата
attempt to perform arithmetic on a nil value
Цитата
stack traceback:
[C]: in metamethod 'add'
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Второй раз в 9.1:
Цитата
Старатель написал:
Код
local hour = 0+os.date('%H')
выскочила такая ошибка:
Цитата
attempt to perform arithmetic on a nil value
Цитата
stack traceback:
[C]: in metamethod 'add'

Также ошибка
Цитата
attempt to call a nil value (method 'pop')
в 9.1 никуда не пропала.

Откуда здесь nil?
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Старатель, добрый день!

Описанные проблемы изучаются. Постараемся в ближайшее время дать ответ.
 
Цитата
Старатель написал:
Старатель  написал:
local hour = 0+os.date('%H')
выскочила такая ошибка: attempt to perform arithmetic on a nil value
 Меня заинтриговала ошибка, которую вы обнаружили, в таком коротком коде.
Напишите, пожалуйста:
  Как часто выполняется в скрипте приведенный вами фрагмент?
  Где это выполняется: в main или колбеках?
-----------------------
Цитата
Старатель написал:
Также  ошибка attempt to call a nil value (method 'pop') в 9.1 никуда не пропала. Откуда здесь nil?
В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades.
В API QLua есть функции реализации потокобезопасной очереди, созданные разработчиком QUIK:  table.sinsert, table.sremove.
Пример использования потокобезопасной очереди: https://forum.quik.ru/messages/forum10/message56397/topic6356/#message56397
 
Цитата
TGB написал
Пример использования потокобезопасной очереди:  https://forum.quik.ru/messages/forum10/message56397/topic6356/#message56397
table.sinsert неприменима в случаях, когда очередь имеет большую длину. Использовать такой код нужно с осторожностью.
 
Цитата
TGB написал:
Как часто выполняется в скрипте приведенный вами фрагмент?
Минимальный интервал 1 мс. Но может быть и больше в зависимости от различных факторов, в т.ч. от текущего Timer Resolution

Цитата
TGB написал:
Где это выполняется
в main

Цитата
TGB написал:
В API QLua есть функции реализации потокобезопасной очереди, созданные разработчиком QUIK:  table.sinsert, table.sremove.
Пример использования потокобезопасной очереди
В качестве разминки сделайте перезаказ обезличенных сделок (или переключитесь на другой сервер) ближе к концу торговой сессии и посмотрите, с какой задержкой будет обрабатываться ваша очередь и расход памяти скриптом. Задержка вычисляется как разница между временем получения колбека и фактическим временем обработки его в main.
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
TGB написал:
В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades.
И?
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
TGB написал:
В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades.  В API QLua есть функции реализации потокобезопасной очереди, созданные разработчиком QUIK:  table.sinsert, table.sremove. Пример использования потокобезопасной очереди:  https://forum.quik.ru/messages/forum10/message56397/topic6356/#message56397
На самом деле, push выполняется только в потоке коллбэков, pop и size -- только в main-потоке. Очередь, реализованная Старателем, в этом случае корректно работает и без блокировок.

Ошибки типа os.date() == nil означают, что где-то глубоко в QLua что-то не так. У меня подобное было в 2014-2015 годах, потом прошло и уже давно не было. Возможно, в 9-й версии опять что-то не так.
 
Цитата
Старатель написал:
В качестве разминки сделайте перезаказ обезличенных сделок (или переключитесь на другой сервер) ближе к концу торговой сессии и посмотрите, с какой задержкой будет обрабатываться ваша очередь и расход памяти скриптом.
  Очередь не моя, а разработчика QUIK.
  Мне не известно как вы обрабатываете обезличенные сделки (сколько это может занимать ресурсов ПК), поэтому я запустил тест для проверки времени выполнения потокобезопасных функций реализации только очереди:
Код
----  Скрипт -тест  ----
 --  Этот фрагмент выполняется  ~500 милисекунд ---
local T = {}
local v
for j = 1, 10  do 
  for i = 1, 1000 do  --- запись в очередь
     table.sinsert  (T, {'sdfdfmffmf', 57})
--     v = T[1]
--    table.sremove(T, 1)
  end

  for i = 1, 1000 do  --- чтение из очереди
 --    table.sinsert  (T, {'sdfdfmffmf', 57})
     v = T[1]
    table.sremove(T, 1)
  end
end


  10000 обращений (запись, чтение, удаление) за 500 миллисекунд.
Понятно, что тест искуственный (без взаимодействия с колбеками), но какое то представление о скорости работы очереди и допустимой ее длине он дает.
Заметного роста памяти QLua я не заметил.

Цитата
Старатель написал:
Цитата TGB  написал: В вашем коде, по вашей ссылке, используется в двух потоках потоконебезопасная очередь OnAllTrades.
И?
Это значит, что при работе с такой очередью могут возникать ошибки синхронизации, которые могут порождать наблюдаемые вами последствия.

==========================
Цитата
_sk_ написал:
Очередь, реализованная Старателем, в этом случае корректно работает и без блокировок.
  А что же ситуации время от времени возникают?
 
Цитата
TGB написал:
при работе с такой очередью могут возникать ошибки синхронизации, которые могут порождать наблюдаемые вами последствия.
Абсолютно беспочвенное утверждение, говорящее об отсутствии понимания работы обсуждаемого кода.

Цитата
TGB написал:
запустил тест для проверки времени выполнения потокобезопасных функций реализации только очереди
Тест ни о чём.
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
Старатель написал:
Абсолютно беспочвенное утверждение, говорящее об отсутствии понимания работы обсуждаемого кода.
 Вы имеете ввиду, что для записи и чтения в очередь используются свои указатели и, я бы с вами согласился, если бы не существовал общий объект, в котором это происходит (таблица хранения очереди в которую вставляются и из которой вычеркиваются элементы очереди). Вы уверены, что работа с таблицей при изменении ее структуры в Lua реализована потокобезопасно? Где это написано?
 
TGB, если в представленном коде и возникают, как вы утверждаете, какие-то "ошибки синхронизации, которые могут порождать" пропажу метода pop, используемого только для чтения (!), то это уже вне зоны ответственности скриптера, а ошибка в реализации многопоточной модели QLUA.
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
TGB написал:
Цитата
Старатель написал:
Абсолютно беспочвенное утверждение, говорящее об отсутствии понимания работы обсуждаемого кода.
  Вы имеете ввиду, что для записи и чтения в очередь используются свои указатели и, я бы с вами согласился, если бы не существовал общий объект, в котором это происходит (таблица хранения очереди в которую вставляются и из которой вычеркиваются элементы очереди). Вы уверены, что работа с таблицей при изменении ее структуры в Lua реализована потокобезопасно? Где это написано?
Разработчики ARQA, как я помню, утверждали с самого начала, что примитивные переменные и таблицы Lua не портятся при параллельном их изменении из разных потоков с помощью атомарных операций присваивания. Другое дело, что для таблиц это на самом деле может быть не так. Функции типа table.sinsert, table.sremove и т.п. пришлось вводить, т.к. они не атомарные и занимаются сдвигом внутренних элементов. Все ли подобные неатомарные штуки были "выловлены" разработчиками ARQA -- неизвестно. Если не все, то единственный адекватный вариант -- это создавать структуру в потоке коллбэков, потом table.sinsert, а в main-потоке делать table.sremove.

Теперь про "пропажу" функции pop(). Не исключаю, что время от времени терминал QUIK или операционная система занимаются неким "переносом данных внутри своей памяти" (например, при сборке мусора) во время которого оказывается, что функция pop ещё не определена (не успели её перенести) в новом месте, а её вызывают из другого потока. Но это уже мои домыслы.
 
https://forum.quik.ru/messages/forum10/message8885/topic962/#message8885
 
Цитата
Старатель написал:
это уже вне зоны ответственности скриптера, а ошибка в реализации многопоточной модели QLUA.
1. Для устранения вашей конкретной ситуации, возможно, подойдет вариант реализации очередей, приведенный в моем комментарии https://forum.quik.ru/messages/forum10/message57219/topic6198/#message57219
2. Вообще, существует сравнительно несложный вариант заметно улучшить QLua (сделав его однопоточным для скриптера) без изменения его внутренней архитектуры:
1) добавить в API QLua функцию <задание схемы обработки колбеков>, которую скриптер может (но не обязательно) вызвать в начале своего скрипта с параметром задания схемы;  если эта функция не вызвана, то колбеки обрабатывыются так, как это делается сейчас по старой схеме;  дополнительно, в этой функции можно бы задавать версию Lua, а возможно и еще что-нибудь;  при задании новой схемы, внутри QLua автоматически реализуется схема взаимодействия main с колбеками через две потокобезопасные эффективные очереди (как обеспечить их эффективность, наверное, понятно), одна из которых обслуживает колбеки фондового рынка, а вторая, колбеки событий таблиц QUIK, созданных скриптером;
2) при работе по новой схеме обработки колбеков, в API QLua добавить еще две функции: <функция подписки на события фондового рынка> и <функция подписки на события пользовательских таблиц >; в этих функциях скриптер может, в виде списка (в таблице) подписаться на события в соответствии с существующими именами колбеков;  реализация подписки разработчиком QUIK может быть сведена к автоматическому созданию (скрытых) от пользователя функций колбеков, вызываемых, как это делается сейчас, и записывающих свои параметры с добавлением «от кого параметры» в соответствующие очереди;
3) для работы с очередями по новой схеме в API QLua добавить две функции чтения (?возможно также и выполнения некоторых дополнительных функций), соответственно очередям;  при чтении очередей в считываемой таблице передаются: <имя события>, <время записи в очередь>, <параметры в том виде, как они описаны, в существующих колбеках>.
   При работе по второй схеме, QLua для скриптера становится однопоточным и снимаются многие сложные проблемы. Причем, остается возможность не затрагивать и тех скриптеров, которые по тем или иным причинам не станут уходить от старой схемы.
----
 Общая схема работы скриптера в новой схеме обработки событий QUIK.
<Заказывается новая схема обработки событий >
<Выполняется подписка (вместо написания функций колбеков) на обрабатываемые события QUIK>
<В функции main, в цикле  читаются две очереди и обрабатываются считанные параметры событий>
-------
 Мною была описан некий, как мне представляется, не сильно сложный вариант реализации избавления QLua от проблем параллелизма, связанных с его существующей реализацией.
 
Цитата
Старатель написал:
local hour = 0+os.date('%H') выскочила такая ошибка: attempt to perform arithmetic on a nil value
  Ошибка, которую вы обнаружили, замечательна своей локализацией (всего одна строка кода).
---
  Я посмотрел в исходниках Lua 5.3 код функции os.date и то, как она вызывается на исполнение в коде Lua. Этот код не блокирует потоки в текущей версии QLua 5.3 (и это легко проверить).  При этом, os.date, формально, не является C-функцией, так как в внутри ее кода, без блокировки, используется среда исполнения  Lua (ее внутренние функции), формально не гарантирующая корректного параллелизма при ее использовании.  Это же относится к некоторым другим библиотечным функциям Lua, имеющим признак C-функций. В C-функциях можно использовать только C-API Lua. Использование внутренних функции Lua, без блокировки, в коде C-функций является ошибкой.
  В версии Lua 5.3 (а возможно и в 5.4), похоже, есть «дыра» в некоторых ее стандартных функциях, для работы с ними из разных потоков.
  При работе в однопоточном варианте Lua такая «дыра» проявить себя не может. Но, собственно, разработчики Lua не один раз заявляли, что поддерживают однопоточный вариант Lua, а остальное факультатив, с которым надо разбираться тем, кто встраивает Lua в свои решения.
------
   Конечно, можно попытаться анализировать  все коды стандартных функций с используемыми внутренними функциями Lua без блокировки («раскручивая» соответствующие цепочки вызовов внутренних функций Lua) с целью выяснения, вдруг, случайно, какие то, из них, корректны при работе в нескольких потоках. Но по-хорошему, при написании всех кодов модулей библиотечных функции Lua, из ее среды исполнения, должно быть доступно только ее API (обеспечивающее корректность обращения к Lua из разных потоков).
   В принципе, для разработчика QUIK есть простой вариант исправления, в исходниках QLua, стандартных функций с используемыми внутренними функциями Lua без блокировки:
в начале кода таких функций выполняется lua_lock, а при выходах из них (! их может быть несколько) выполняется lua_unlock.
 
Цитата
TGB написал:
10000 обращений (запись, чтение, удаление) за 500 миллисекунд.
Не смотря на то, что сам тест бестолковый, но холостой цикл за 0,5 сек не слишком ли много?

Цитата
TGB написал:
Заметного роста памяти QLua я не заметил.
Таблица из 1000 строк длиной 10 байт каждая. Какой "рост" вы рассчитывали увидеть в таком тесте?

Цитата
TGB написал:
Для устранения вашей конкретной ситуации, возможно, подойдет вариант реализации очередей, приведенный в моем комментарии
Это не моя ситуация, а разработчиков QLua ))
И не увидел в вашем комментарии каких-то существенных отличий касательно использования метода pop().
Больше похоже на спам вашего  OS_...
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
Старатель написал:
И не увидел в вашем комментарии каких-то существенных отличий касательно использования метода pop().Больше похоже на спам вашего  OS_...
  Вы в комментарии https://forum.quik.ru/messages/forum10/message57219/topic6198/#message57219
 читали это:
2. Существенная особенность построения очередей в OS_Quesha состоит в том, что они строятся на таблицах, в которых после их создания, нет вставок или удалений их полей (записей). В процессе работы с очередями изменяются только значения существующих полей, обеспечивающих запись/чтения этих очередей. Структура таблиц очередей «заморожена». Это обеспечивает в многопоточном режиме возможность эффективной синхронизации работы с очередями на уровне их полей, а не на глобальном уровне самих очередей.
 Так вот, эта существенная особенность обеспечивает то, что приведенный в комментарии конкретный код модуля Queue_safe создания очередей между колбеками и main является потокобезопасным в существующем QLua, в отличие от выложенного вами Queue, который потокобезопасным не является, о чем я уже писал в этой ветке.
 
TGB, слишкоммногабукв, не обратил внимание на цикл
Код
for i =1, size_Queue do 
   cycl[i] = 0 
end


Цитата
TGB написал:
выложенного вами Queue, который потокобезопасным не является

Это уже пусть представители Арки комментируют, насколько безопасными являются действия типа
Код
a={}
a.xxx = 1
a.yyy = 2
a.xxx = nil
и код в сообщении #24 в частности.
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
TGB написал:
TGB  написал:10000 обращений (запись, чтение, удаление) за 500 миллисекунд.Не смотря на то, что сам тест бестолковый, но холостой цикл за 0,5 сек не слишком ли много?
  Опять неточность (мы же обсуждаем код Queue_safe).
В моем обсуждаемом коде Queue_safe во фрагменте тестирования указано:
 --  1.  Этот фрагмент (использование потокобезопасных функций QLua)   (100 000 записей и чтений)  выполняется за ~3560 милисекунд ---
  ................
  --  2. Этот фрагмент (использование Queue_safe)   (100 000 записей и чтений)  выполняется за ~55 милисекунд ---
 
TGB,
https://forum.quik.ru/messages/forum10/message57185/topic5823/#message57185
Это ваше сообщение?
Я не могу быть заинтересован в устранении ошибок в чужом ПО больше, чем его разработчик.
 
Цитата
Старатель написал:
TGB ,  https://forum.quik.ru/messages/forum10/message57185/topic5823/#message57185 Это ваше сообщение?
Это мое сообщение, но
Цитата
TGB написал:
мы же обсуждаем код Queue_safe
 
Цитата
Старатель написал:
код в сообщении  #24  в частности.
      Выполненные мною в Lua 5.3 (5.4) тесты атомарности операций вставки/удаления полей в таблицу показали, что эти операции (в условиях реализован-ной многопоточности QLua) все-таки атомарны.  Возможно?, есть ситуации, не охваченные тестированием, когда атомарности может не быть. Если же таких ситуаций нет, то мое утверждение, что выложенный Старателем код Queue (с описанием редко возникающей ошибки) создает потокоопасные очереди, ошибочное.
Страницы: 1 2 След.
Читают тему (гостей: 1)
Наверх