Здравствуйте! В созданном год назад скрипе использовалась функция getMoney. Возникла необходимость использовать функцию getMoneyEx local t = getMoneyEx(FirmID, ClientCode, Tag, CurCode, 1) для получения остатка на Т1. Скрипт стал эпизодически вылетать по ошибке. Оказалось, что getMoneyEx иногда(до 10 раз за торговую сессию) выдает nil. Пришлось вставить проверку на nil и использовать предыдущее сохраненное значение t.currentbal. Технически такое решение меня устраивает, но осадок остался. Что скажете, господа из техподдержки?
Функция возвращает таблицу Lua с параметрами таблицы «Позиции по деньгам».
В случае ошибки функция возвращает «nil».
Что за ошибка у вас или не у вас возникает -- неясно, но раз в документации написано, что может быть nil, это надо предусматривать. Но осадочек остаётся, согласен.
- Здравствуйте, Сэр! Ваше обращение получено, проблема изучается. Постараемся в ближайшее время дать ответ.
И дальше две модели - синхронная и асинхронная. Синхронная - это как форум, задал вопрос, через некоторое время зашел, поглядел, что ответили, если ничего - попозже еще зашел и так далее. Асинхронная - это оставил мыло (колбек), как проблему изучили, прислали ответ туда. Тут тоже возможны варианты, можно написать "ответ на ваш вопрос появился на форуме", то есть просто напомнить, что пора пойти и синхронно глянуть, либо прислать ответ целиком, чтобы никуда уже не ходить. В квике есть все эти варианты для разных вопросов. В идеальном мире были бы возможны все варианты для любого вопроса по выбору скрипта. Скажем, мне вот не нужна в OnAllTrade вся эта табличка с трейдом, мне нужен только факт, что туда что-то приехало, а бедный квик каждый раз табличку заполняет, в которую я даже не погляжу. А кому-то табличка нужна.
Anton написал: И дальше две модели - синхронная и асинхронная. Синхронная - это как форум, задал вопрос, через некоторое время зашел, поглядел, что ответили, если ничего - попозже еще зашел и так далее. Асинхронная - это оставил мыло (колбек), как проблему изучили, прислали ответ туда. Тут тоже возможны варианты, можно написать "ответ на ваш вопрос появился на форуме", то есть просто напомнить, что пора пойти и синхронно глянуть, либо прислать ответ целиком, чтобы никуда уже не ходить. В квике есть все эти варианты для разных вопросов. В идеальном мире были бы возможны все варианты для любого вопроса по выбору скрипта. Скажем, мне вот не нужна в OnAllTrade вся эта табличка с трейдом, мне нужен только факт, что туда что-то приехало, а бедный квик каждый раз табличку заполняет, в которую я даже не погляжу. А кому-то табличка нужна.
Что выгодней с точки зрения производительности: постоянно опрашивать размер таблицы
Код
function main()
local last = 0
while run do
local n = getNumberOf("all_trades")
if n > last then
for i = last, n - 1 do
...
end
last = n
else sleep(100) end
end
end
или назначить колбек на получение новых данных?
Код
function OnAllTrade()
a = true
end
function main()
local last = 0
while run do
if a then
local n = getNumberOf("all_trades")
a = false
for i = last, n - 1 do
...
end
last = n
else sleep(100) end
end
end
В общем случае колбек - это более грамотный способ. Если вы опрашиваете таблицу терминала на предмет получения новой записи и делаете это много раз в секунду, в большинстве случаев вы не получите факта изменений и будете гонять терминал впустую. Если же вы получили колбек и исходя из этого факта полезли в таблицу - это эта работа уже является полезной, а не бессмысленной.
Незнайка написал: Что выгодней с точки зрения производительности
Думаю, в приведенном виде вариант с колбеком будет медленнее в целом, сначала квик лезет в таблицу, чтобы дернуть колбек, потом мейн лезет в таблицу, чтобы получить данные. Этот вариант более интересен, когда мейн не крутится в цикле, а стоит на событии, тогда в неактивное время он вообще не просыпается. Но это уже подразумевает длл, в луа таких сущностей нет. А так вообще ворос более архитектурный, если охота event-driven, кроме колбека и вариантов нет, пусть бы и медленнее.
s_mike@rambler.ru написал: Если же вы получили колбек и исходя из этого факта полезли в таблицу - это эта работа уже является полезной, а не бессмысленной.
Но при этом терминал упаковывает и передаёт нам в колбеке табличку, которую мы всё равно не используем. Или если использовать OnAllTrade() без параметров, то он не упаковывает сделку в табличку? Опять же вопрос: что выгоднее перенести таблицу со сделкой в main через потокобезопасные функции или вытащить её в main через getItem?
Да указатель он передаёт - что ему, заняться больше нечем, кроме как "табличку упаковывать"? Впрочем, я уже ничему не удивлюсь. Лично я убил коллбек OnOrder и оставил только OnTrade, а цены опрашиваю примерно раз в секунду через getParamEx. ИМХО, самое разумное.
Выгоднее информацию из колбека сохранить в скрипте и оперировать в дальнейшем уже этой информацией
дело в том, что qlua - это пришлепка сбоку к терминалу, общающаяся с ним через тоненькую дырдочку. Поэтому любая операция получения информации из терминала в луа несёт значительно бОльшие затраты, чем оперирование этими же данными в самом скрипте.
только нужно иметь ввиду, что встроенные функции типа table.sinsert приемлемо работают при небольших размерах массивов, при увеличении размеров скажем до миллиона записей в нем начинается беда.
Не в этом случае. Хранилище асинхронное. Можно либо сразу вытащить всю запись и передать по значению, как и сделано, либо держать лок до возврата колбека, что есть идиотизм, либо передать индекс записи и объяснять потом пользователям, почему иногда возвращается ничего. Максимальное улучшение тут видимое - посмотреть при старте скрипта на сигнатуру колбека и не заполнять табличку, если она ему не нужна. Но это из области полировки.
Anton, В этом! Хранилище по определению асинхронное. И информацию о сделках Квик всё равно хранит у себя. Так что можно просто передать указатель на запись (ну или хотя бы индекс записи) и не объяснять потом пользователям ничего, поскольку программа должна быть нормально отлажена. А уж "смотреть при старте скрипта на сигнатуру колбека и не заполнять табличку, если она ему не нужна" - это в морг! И так уже затрахали своим долбаным интеллектом - достаточно посмотреть хотя бы на эту долбаную "таргетированную рекламу".
Владимир написал: можно просто передать указатель на запись
... и держать лок хранилища, чтобы оно не дай бог что-нибудь там внутри не подвинуло, пока юзер в колбеке ковыряется. Вариант выше упомянут и признан идиотским, каковым он и является. Прочие варианты тоже перечислены и это полная группа, отлаживай не отлаживай. Раз хранилище асинхронное, оно вольно асинхронно очиститься в том числе, и индекс тоже инвалидирутеся. Крэша он не вызовет, а нил вернет, и объяснять придется.
Anton, Если индекс понимать как здесь - по виду индекс, по факту имя - то именно так всё и будет. И глюки при удалении строк или сортировке таблицы как неизбежное следствие. А если это UID, то никто ничего никогда никуда не подвинет. Идиотизм - копировать юзеру всю колоду данных вместо того, чтобы дать ему один этот UID - и пусть читает по нему, чего хочет. Временные затраты при этом просто РАВНЫ нулю! Подумаешь, "хранилище асинхронное"...
нет в базе данных терминала адреса строки или чего то ещё, описывающей сущность типа сделка, лимит или позиция по фьючерсам. Невозможно передать адрес этой сущности. Хранилище не есть примитивный массив, это база. Уж не говоря о безопасности.
нет в луа стандартных средств для прямого лазанья по памяти указателем.
квалификации разработчиков терминала вполне достаточно, чтобы правильно решать тривиальные вопросы типа "передать ссылку или значение", можете не сомневаться.
Я чуть не всю жизнь занимался сложными базами данных, и утверждаю, что ЕСТЬ "в базе данных терминала адреса строки или чего то ещё, описывающей сущность". По той простой причине, что доступ к любому элементу данных ДОЛЖЕН быть обеспечен.
Никто и не просит "передать адрес этой сущности" - это даже для СУБД недопустимо! Ну, в крайнем случае, для ядра СУБД, если "уж замуж невтерпёж". Но вот обеспечить корректную работу с UID (для разных уровней доступа они могут быть разными) любая уважающая себя СУБД просто ОБЯЗАНА!
Квик написан БЕЗОБРАЗНО - примеров тому несть числа, а потому говорить о его хранилище как о базе можно разве что в ироничном ключе.
В луа нет даже целочисленных типов данных - какое уж тут "прямое лазанье по памяти указателем". Да и ни один уважающий себя разработчик такого не позволит.
Охотно верю, что "квалификации разработчиков терминала вполне достаточно, чтобы правильно решать тривиальные вопросы типа "передать ссылку или значение", но вот вопрос: а они её ПЕРЕДАЮТ? Или всё-таки " заполняют табличку"?
Владимир написал: Я чуть не всю жизнь занимался сложными базами данных, и утверждаю, что ЕСТЬ "в базе данных терминала адреса строки или чего то ещё, описывающей сущность". По той простой причине, что доступ к любому элементу данных ДОЛЖЕН быть обеспечен.
Особенно в trie, там одни строки и есть. Но есть нюанс.
Anton, Что за зверь trie? Префиксное дерево, что ли? Так ведь ЛЮБОЙ набор данных можно представить либо в виде массива (например, байт) - в этом случае должен быть известен его размер, либо в виде строки - в этом случае нужно знать значение терминатора. В обоих случаях нужно знать место начала этого набора (адрес или лучше UID). Да и какие могут быть "нюансы" в несчастном дереве? Данные в реальности куда более сложно организованы и могут быть представлены только графом общего вида.
swerg, Я уже просил (не помню, Вас или нет): не надо врать! Это про "не читает документацию". А как передаются параметры в Lua, мне АБСОЛЮТНО до лампады - я не разработчик языка, я просто пользователь. Просто ЕСЛИ они передаются не ссылкой, а самой таблицей значений, ТО это есть идиотизм. Идиотизм тех, кто ПИШЕТ эту самую "документацию".
Владимир написал: А как передаются параметры в Lua, мне АБСОЛЮТНО до лампады - я не разработчик языка, я просто пользователь. Просто ЕСЛИ они передаются не ссылкой, а самой таблицей значений, ТО это есть идиотизм.
Мне кажется, что вы зря "наезжаете" на язык Lua. Переключесть на C++ и будет вам счастье (и это обеспечивает Lua). Все, что вы не можете реализовать в собственно Lua (а это то очень мало), вы можете реализовать в C++.
TGB, Я вовсе не "наезжаю на Lua" - меня язык полностью устраивает. В смысле, язык-то поганый, но я уже реализовал на нём всю необходимую мне функциональность - осталось мелкая шлифовка, но это уже в фоновом режиме, не горит. И мне нафиг не нужен C++, тем более, что я его терпеть не могу, и всю жизнь писал на чистом С. Но для этих задач и С не нужен - есть Lua, и даже его здесь вполне достаточно.