Mikhail Sukhov
|
Date: 3/26/2011
aspirant:
Dictionary отсортировал бы свои элементы по алфавиту (ключи ведь string).
Ты путаешь с SortedDictionary. И то там не по алфавиту... Это хеш алгоритм. Там сортировка не нужна. Группировка значения идет по хэшу ключа. Соответственно, когда обращаемся по ключу, сначала берется его хэш (PlazaColumn.GetHashCode) и получаются все значения, соответствующие хэшу. Операция O(1). И далее, если у нас коллизия, перебором всех ключей идет сравнение (PlazaColumn.Equals) и находится первый попавшийся (ага, уникальность там не проверяется).
Итого, в лучшем варианте O(1). В худшем O(n). Но чтобы добиться последнее, надо еще постараться.[smile]
|
|
|
|
Thanks:
|
|
|
|
|
|
aspirant
|
Date: 3/26/2011
Mikhail Sukhov:
aspirant:
Dictionary отсортировал бы свои элементы по алфавиту (ключи ведь string).
Ты путаешь с SortedDictionary. И то там не по алфавиту... Это хеш алгоритм. Там сортировка не нужна. Группировка значения идет по хэшу ключа. Соответственно, когда обращаемся по ключу, сначала берется его хэш (PlazaColumn.GetHashCode) и получаются все значения, соответствующие хэшу. Операция O(1). И далее, если у нас коллизия, перебором всех ключей идет сравнение (PlazaColumn.Equals) и находится первый попавшийся (ага, уникальность там не проверяется).
Итого, в лучшем варианте O(1). В худшем O(n). Но чтобы добиться последнее, надо еще постараться.[smile]
Да, насчет сортировки я был не прав.
|
|
|
|
Thanks:
|
|
|
|
|
|
Mikhail Sukhov
|
Date: 3/26/2011
|
|
|
|
|
aspirant:
Я изменил класс PlazaListener. Посмотри, пожалуйста, нужны твои комментарии + желательно кусок псевдокода - твое видение, как пользователь создает таблицу с набором колонок для передачи ее в PlazaListener.
Посмотрел и доделал кое-что.
Рассмешило название PlazaPartColumns. Долго думал, что за "часть". Оказалось, это Партфэл, дарагой!
Что осталось до переделать:
- Сейчас PlazaListener создается в самом начале со всеми колонками. Как я уже писал, использовать надо только те колонки, что определены схемами PlazaTable.Columns.
- PlazaListener выглядит как лишний класс (возможно, что в него потом будет засунута еще какая-то логика, если да, то какая?). Что он делает сейчас. Берет данные из PlazaStream и передает их в PlazaTrader. Тоесть, такой бюрократически посредник, который бумажки из стола на стол несет.
- enum TableName лучше сделать статическим классом со строковыми константами. Я так понял, такие безобразные названия нужны лишь для того, чтобы ini файлы создавать? Если да, то по логике простой. Мы создаем текстовый файл, используем string. Вся логика в имени полей TableName - приведение в string... Так может тогда сразу сделать string?
- Давайте подумаем насчет фильтрации. Сейчас это выглядит как то не очень. Аспирант, ты же вроде как уже что-то делал по фильтрам?
- PlazaSchemaParser предлагаю упрятать в PlazaTableSerializer.
|
|
|
|
Thanks:
|
|
|
|
|
|
skuvv
|
Date: 3/26/2011
aspirant:
skuvv:
К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру).
Получается, ты делал свою реализацию PlazaTrader?
Нет у меня не интерфейс как в s#, а напрямую работа c потоками и событиями
|
|
|
|
Thanks:
|
|
|
|
|
|
Mikhail Sukhov
|
Date: 3/26/2011
skuvv:
aspirant:
skuvv:
К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру).
Получается, ты делал свою реализацию PlazaTrader?
Нет у меня не интерфейс как в s#, а напрямую работа c потоками и событиями
Может выложить это ввиде отдельного теста для сравнения перфоманса? Насчет OnNewSecurityChanged - конечно. Если вместо поиска по словарю устраивать Exist Find и т.д., то я не удивлюсь и пол минутными задержками.[smile]
|
|
|
|
Thanks:
|
|
|
|
|
|
aspirant
|
Date: 3/26/2011
|
|
|
|
|
Mikhail Sukhov:
Сейчас PlazaListener создается в самом начале со всеми колонками. Как я уже писал, использовать надо только те колонки, что определены схемами PlazaTable.Columns.
Как клиентский код создает таблицу с колонками и схемами? Твое видение с куском кода.
Mikhail Sukhov:
enum TableName лучше сделать статическим классом со строковыми константами. Я так понял, такие безобразные названия нужны лишь для того, чтобы ini файлы создавать? Если да, то по логике простой. Мы создаем текстовый файл, используем string. Вся логика в имени полей TableName - приведение в string... Так может тогда сразу сделать string?
Этот enum был служебным, для внутреннего пользования. Клиенту его можно не показывать. Зачем я его сделал? Когда нужно набить пару десятков классов, enum + intellisense здорово помогает. Потом подстраховка от случайное опечатки в string. Сам я его не набивал: вместо этого пропарсил папку со всеми схемами.
Вообще PlazaTable сейчас и есть то, что ты предлагаешь. За исключением полей метаданных все остальные методы закомментены (причем, делал это не я). Можно сделать вот так:
// вместо: public TableName SystemName { get; private set; }
public string SystemName { get{ _systemName.ToString(); }
Mikhail Sukhov:
Давайте подумаем насчет фильтрации. Сейчас это выглядит как то не очень.
Я вообще собирался это делать внутри PlazaListener, но пока думал, skuvv успел привинтить свой фильтр[smile]. Что насчет методов RegisterSecurity/UnRegisterSecurity? С помощью них будем включать фильтрацию или они нужно для чего-то другого?
Mikhail Sukhov:
PlazaSchemaParser предлагаю упрятать в PlazaTableSerializer
Сделаю, когда устаканится модель метаданных. С тех пор как я написал PlazaSchemaParser, модель уже раза-три менялась, и я решил отложить доделку этого класса на самый конец.
|
|
|
|
Thanks:
|
|
|
|
|
|
skuvv
|
Date: 3/26/2011
|
|
|
|
|
Mikhail Sukhov:
skuvv:
aspirant:
skuvv:
К примеру я сравнил проект со своей старой программой plaza2, данные в текущий s# проект поступают медленнее на 6-10мс(время снимал с OnNewSecurityChanged к примеру).
Получается, ты делал свою реализацию PlazaTrader?
Нет у меня не интерфейс как в s#, а напрямую работа c потоками и событиями
Может выложить это ввиде отдельного теста для сравнения перфоманса? Насчет OnNewSecurityChanged - конечно. Если вместо поиска по словарю устраивать Exist Find и т.д., то я не удивлюсь и пол минутными задержками.[smile]
void m_conn4_StreamDataInserted(CP2DataStream stream, String tableName, CP2Record rec)
{
try
{
if (stream.StreamName == streamFutCommonID)
{
int index = instruments.GetIndex(rec.GetValAsLong("isin_id"));
if(index>=0)
{
double best_sell = Convert.ToDouble(rec.GetValAsVariant("best_sell"));
double best_buy = Convert.ToDouble(rec.GetValAsVariant("best_buy"));
if (best_buy != 0 && best_sell != 0)
{
instruments._bestask[index] = best_sell;
instruments._bestask_vol[index] = rec.GetValAsLong("amount_sell");
instruments._bestbid[index] = best_buy;
instruments._bestbid_vol[index] = rec.GetValAsLong("amount_buy");
instruments._lasttrade[index] = Convert.ToDouble(rec.GetValAsVariant("price"));
instruments._lasttrade_vol[index] = rec.GetValAsLong("amount");
instruments._lasttrade_time[index] = Convert.ToDateTime(rec.GetValAsString("deal_time"));
instruments._bidask_time[index] = DateTime.Now;
curr_rev_futcommon = rec.GetValAsLong("replRev");
log_buffer.Add(t4.Name, rec.GetValAsString("replID") + ";" + rec.GetValAsString("replRev") + ";" + instruments._isin_id[index] + ";" + instruments._bestask[index] + ";" + instruments._bestask_vol[index] + ";" +
instruments._bestbid[index] + ";" + instruments._bestbid_vol[index] + ";" + instruments._lasttrade[index] + ";" + instruments._lasttrade_vol[index] + ";" + instruments._lasttrade_time[index].ToString(timefmt) + ";" + rec.GetValAsString("deal_count") + ";" + rec.GetValAsString("pos"));
}
}
}
}
catch (Exception e)
{
log_buffer.Add("error", "[" + t4.Name + "] " + e.ToString());
}
}
Event datainserted
Все типы таблицы я получал в соответсвующих им win thread.
Событий никаких нет [biggrin], заполняется статик массив instruments,а роботы на каждом прогоне его чекают.
Ну и в конце запись в текстовики, через самописный логгер.
ps фильтрация опять же массиву instruments
|
|
|
|
Thanks:
|
|
|
|
|
|
Mikhail Sukhov
|
Date: 3/27/2011
|
|
|
|
|
aspirant:
Mikhail Sukhov:
Сейчас PlazaListener создается в самом начале со всеми колонками. Как я уже писал, использовать надо только те колонки, что определены схемами PlazaTable.Columns.
Как клиентский код создает таблицу с колонками и схемами? Твое видение с куском кода.
Взял за основу отсюда:
PlazaTableRegistry.FutCommon.Columns.Add(PlazaColumnRegistry.FuturesCommon.CurKotir);
PlazaTableRegistry.FutAggr5.Columns.Add(PlazaColumnRegistry.FuturesAggregation5.Moment);
aspirant:
Mikhail Sukhov:
enum TableName лучше сделать статическим классом со строковыми константами. Я так понял, такие безобразные названия нужны лишь для того, чтобы ini файлы создавать? Если да, то по логике простой. Мы создаем текстовый файл, используем string. Вся логика в имени полей TableName - приведение в string... Так может тогда сразу сделать string?
Этот enum был служебным, для внутреннего пользования. Клиенту его можно не показывать. Зачем я его сделал? Когда нужно набить пару десятков классов, enum + intellisense здорово помогает. Потом подстраховка от случайное опечатки в string. Сам я его не набивал: вместо этого пропарсил папку со всеми схемами.
Ок, не поняли друг друга. Тогда ремарка и код. Если enum используется для задания строковых констант, то используется класс со строками:
static class TableName
{
public const string BaseContractsParams = "base_contracts_params";
..
}
public static PlazaTable FutAggr50 = new PlazaTable(TableName.BaseContractsParams, ReplicationStream.FutAggr50, "Фьючерсы: стакан глубиной 50 котировок");
На этом примере сразу видно недостаток именования перечислений (не ReplicationStreams, а ReplicationStream). Сходу кажется, что идет работа с потоком. А на самом деле к потокам это имеет о посредственное значение.
aspirant:
Вообще PlazaTable сейчас и есть то, что ты предлагаешь. За исключением полей метаданных все остальные методы закомментены (причем, делал это не я). Можно сделать вот так:
// вместо: public TableName SystemName { get; private set; }
public string SystemName { get{ _systemName.ToString(); }
Не понял, что за рокировка.
> **[aspirant](@message(7053)):**
> > **[Mikhail Sukhov](@message(7048)):**
> > Давайте подумаем насчет фильтрации. Сейчас это выглядит как то не очень.
> Я вообще собирался это делать внутри PlazaListener, но пока думал, skuvv успел привинтить свой фильтр[smile]. Что насчет методов RegisterSecurity/UnRegisterSecurity? С помощью них будем включать фильтрацию или они нужно для чего-то другого?
Да, именно включение фильтра. Во всех АПИ (и я думаю в Плазе тоже рано или поздно сделают), фильтрация идет на серверной стороне и этот фильтра изменяется через методы, аналогичные Register Unregister.
|
|
|
|
Thanks:
|
|
|
|
|
|
aspirant
|
Date: 3/28/2011
|
|
|
|
|
Mikhail Sukhov:
ODE0�
Вопросы:
- То есть мы исходим из того, что клиент подписывается на каждый поток только один раз? Напоминаю, у Плазы можно подписываться на один поток несколько раз. Клиенты не будут спрашивать? Когда проект будет зарелизен, изменить архитекутру будет сложно.
- Что делать с нашими стандартными потоками, которые нужны, чтобы мапить объекты. Мы договорились, что их скроем от клиента, чтобы гарантировать в них нужный набор колоннок. Придется все равно создавать какие-то отдельные таблицы.
Mikhail Sukhov:
Если enum используется для задания строковых констант, то используется класс со строками:
static class TableName...
OK, сделаю после фильтрации. Сейчас все работает, а это рефакторинг функционала не добавит, только эстетику.
> **[Mikhail Sukhov](@message(7064)):**
> Не понял, что за рокировка.
Теперь она уже не нужна.
> **[Mikhail Sukhov](@message(7064)):**
> На этом примере сразу видно недостаток именования перечислений (не ReplicationStreams, а ReplicationStream)
Не знаю, дело вкуса. Я уже привык к единственному числу. Вот, кстати, MSDN'овский [guideline](http://msdn.microsoft.com/en-us/library/4x252001(v=vs.71).aspx).
|
|
|
|
Thanks:
|
|
|
|
|
|
Mikhail Sukhov
|
Date: 3/28/2011
aspirant:
Вопросы:
- То есть мы исходим из того, что клиент подписывается на каждый поток только один раз? Напоминаю, у Плазы можно подписываться на один поток несколько раз. Клиенты не будут спрашивать? Когда проект будет зарелизен, изменить архитекутру будет сложно.
Что делать с нашими стандартными потоками, которые нужны, чтобы мапить объекты. Мы договорились, что их скроем от клиента, чтобы гарантировать в них нужный набор колоннок. Придется все равно создавать какие-то отдельные таблицы.
Давай еще раз обсудим. С точки зрения практики - зачем это нужно?
Хм, а почему бы просто не оставить как есть сейчас?
|
|
|
|
Thanks:
|
|
|
|
|