Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 18:23
Оценка:
Требуется отображать последние 10000 элементов. Записи порождаются достаточно быстро — около 1000 в минуту их нужно логировать.
Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции.
Но есть несколько проблем — для новых значений создается новый MeasureData со своим DateTime что может съесть память. А также выборка из такого списка не очень удобна учитывая что нужно еще по дате в обратном порятке сортировать — лишние расчеты.
Есть ли готовые списки для этого ?
Re: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
А>Требуется отображать последние 10000 элементов. Записи порождаются достаточно быстро — около 1000 в минуту их нужно логировать.
А>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции. А>Но есть несколько проблем — для новых значений создается новый MeasureData со своим DateTime что может съесть память. А также выборка из такого списка не очень удобна учитывая что нужно еще по дате в обратном порятке сортировать — лишние расчеты.
А>Есть ли готовые списки для этого ?
Есть стандартный FIFO контейнер — Queue<T>. Сортировать не надо, если складывать по мере порождения данных.
Re[2]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 19:28
Оценка:
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>Требуется отображать последние 10000 элементов. Записи порождаются достаточно быстро — около 1000 в минуту их нужно логировать.
А>>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции. А>>Но есть несколько проблем — для новых значений создается новый MeasureData со своим DateTime что может съесть память. А также выборка из такого списка не очень удобна учитывая что нужно еще по дате в обратном порятке сортировать — лишние расчеты.
А>>Есть ли готовые списки для этого ? S>Есть стандартный FIFO контейнер — Queue<T>. Сортировать не надо, если складывать по мере порождения данных.
Не совсем то. Ниже тестовый пример, может я неправильно с ней работаю.
Dequene будет съедать элемент, и второму потоку оно не достанется. самое старое значение должно вытесняться при вставке нового элемента а не при чтении.
Т.е. допустим нам не 10000 нужно записей а иметь "окно" только 5 последних записей.
Соотвественно сначала должно вывестись :
5,4,3,2,1 потом 6,5,4,3,2 , потом 7,6,5,4,3
в обоих потоках.
class Program
{
static Queue<int> q;
static object syncObj = new object();
static void ShowLast5()
{
while (true)
{
// это блокирока чтоб 2 потока по очереди показывали результат 5 сек каждыlock( syncObj )
{
Console.Clear();
Console.WriteLine(string.Format("Last 5 Records from Thread {0}: ", System.Threading.Thread.CurrentThread.ManagedThreadId));
foreach (var i in q)
Console.WriteLine(i);
System.Threading.Thread.Sleep(5000);
}
}
}
static int newitem;
static void Generate()
{
while (true)
{
q.Enqueue(newitem);
newitem++;
System.Threading.Thread.Sleep(15000);
}
}
static void Main(string[] args)
{
q = new Queue<int>(5);
q.Enqueue(1);
q.Enqueue(2);
q.Enqueue(3);
q.Enqueue(4);
q.Enqueue(5);
newitem = 6;
var t1 = new System.Threading.Thread(Generate);
t1.Start();
var t2 = new System.Threading.Thread(ShowLast5);
t2.Start();
var t3 = new System.Threading.Thread(ShowLast5);
t3.Start();
Console.ReadKey();
}
}
Re[3]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, samius, Вы писали:
А>>>Есть ли готовые списки для этого ? S>>Есть стандартный FIFO контейнер — Queue<T>. Сортировать не надо, если складывать по мере порождения данных.
А>Не совсем то. Ниже тестовый пример, может я неправильно с ней работаю. А>Dequene будет съедать элемент, и второму потоку оно не достанется. самое старое значение должно вытесняться при вставке нового элемента а не при чтении.
В стартовом сообщении ничего о потоках не было...
А>Т.е. допустим нам не 10000 нужно записей а иметь "окно" только 5 последних записей. А>Соотвественно сначала должно вывестись :
А>5,4,3,2,1 потом 6,5,4,3,2 , потом 7,6,5,4,3 А>в обоих потоках.
Не понял. Требуется что бы один и тот же контейнер, изменяемый в одном потоке отыграл все свои состояния в других потоках, которые выводят в консоль элементы?
Если так, то мне неясно, как здесь поможет Dictionary...
А>
А> class Program
А> {
А> }
А>
В коде ошибки синхронизации, кроме того по нему не понятно, какая задача решается.
Re: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
А>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции.
Не совсем понятно, почему не подходит обыкновенный List<>?
Re[2]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 21:09
Оценка:
Здравствуйте, dims12, Вы писали:
D>Здравствуйте, Аноним, Вы писали:
А>>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции.
D>Не совсем понятно, почему не подходит обыкновенный List<>?
тормозить будет при вставке элемента в начало или наоборот при удалении из начала.
Re[4]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 21:14
Оценка:
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, samius, Вы писали:
А>>>>Есть ли готовые списки для этого ? S>>>Есть стандартный FIFO контейнер — Queue<T>. Сортировать не надо, если складывать по мере порождения данных.
А>>Не совсем то. Ниже тестовый пример, может я неправильно с ней работаю. А>>Dequene будет съедать элемент, и второму потоку оно не достанется. самое старое значение должно вытесняться при вставке нового элемента а не при чтении. S>В стартовом сообщении ничего о потоках не было...
А>>Т.е. допустим нам не 10000 нужно записей а иметь "окно" только 5 последних записей. А>>Соотвественно сначала должно вывестись :
А>>5,4,3,2,1 потом 6,5,4,3,2 , потом 7,6,5,4,3 А>>в обоих потоках.
S>Не понял. Требуется что бы один и тот же контейнер, изменяемый в одном потоке отыграл все свои состояния в других потоках, которые выводят в консоль элементы? S>Если так, то мне неясно, как здесь поможет Dictionary...
А>>
А>> class Program
А>> {
А>> }
А>>
S>В коде ошибки синхронизации, кроме того по нему не понятно, какая задача решается.
задача простая видеть последние N записей из разных потоков, старые записи должны из списка/очереди удаляться иначе их накопится очень много.
решение на Dictionary вижу примерно следующее.
public class MyQuene
{
private Dictionary<int, MeasureData> quene;
private int currentItem = 0;
private int queneCapacity = 10000;
public PushNewMeasure( p1, p2, p3 )
{
if ( currentItem >= queneCapacity )
{
currentItem=0;
}
quene[ currentItem ] = new MeasureData( p1, p2, p3 );
currentItem++;
}
public MeasureData[] GetMeasures()
{
return
quene.Skip( currentItem ).Take( queneCapacity - currentItem).
Union( quene.Take( currentItem ) )
.Select ( i => i.Value).Reverse().ToArray();
}
}
Re[2]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 21:23
Оценка:
Здравствуйте, dims12, Вы писали:
D>Здравствуйте, Аноним, Вы писали:
А>>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции.
D>Не совсем понятно, почему не подходит обыкновенный List<>?
Вот блин. Оказывается он ничуть не тормозной
Вполне шустро работает. Меньше миллисекунды..196 тиков всего.
А он не двигает все элементы при удаленни чтоли ?
Re[5]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
А>задача простая видеть последние N записей из разных потоков, старые записи должны из списка/очереди удаляться иначе их накопится очень много.
Полагаю, что с этого надо было начать.
А>решение на Dictionary вижу примерно следующее.
А>
Вообще говоря это решение обладает недостатками:
*) записи не удаляются
*) синхронизация отсутствует как класс
*) при добавлении очередного элемента и одновременном выполнении GetMeasures неминуемо исключение
*) записи не упорядоченны и берутся не последние
Re[3]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, dims12, Вы писали:
D>>Здравствуйте, Аноним, Вы писали:
А>>>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции.
D>>Не совсем понятно, почему не подходит обыкновенный List<>?
А>Вот блин. Оказывается он ничуть не тормозной А>Вполне шустро работает. Меньше миллисекунды..196 тиков всего. А>А он не двигает все элементы при удаленни чтоли ?
Двигает. А Queue — нет.
Re[3]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали: А>>>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции. D>>Не совсем понятно, почему не подходит обыкновенный List<>? А>тормозить будет при вставке элемента в начало или наоборот при удалении из начала.
Читайте матчасть. Вставка и удаление из списка выполняются за константное время.
Кроме того, то, что я тут прочитал, наводит меня на мысль, что вполне можно обйтись стандартным деком, который тоже вставку и удаление на концах делает за константное время. А то, что вы тут говорите о потоках — это стандартная задача читатели-писатели. Требует синхронизации доступа к буферу-контейнеру. Это — средствами API — в С++ стандартных средств пока нет.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Аноним, Вы писали: А>>>>Пока вижу варант с Dictionary<int, MeasureData > и переменной с индексом как курсор текущей позиции. D>>>Не совсем понятно, почему не подходит обыкновенный List<>? А>>тормозить будет при вставке элемента в начало или наоборот при удалении из начала. LVV>Читайте матчасть. Вставка и удаление из списка выполняются за константное время.
Речь о дотнете, в нем List-ом называется динамический массив. Соответственно время вставки/удаления линейное.
LVV>Требует синхронизации доступа к буферу-контейнеру. Это — средствами API — в С++ стандартных средств пока нет.
Тема ведь в донтене
Re[6]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 21:33
Оценка:
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>задача простая видеть последние N записей из разных потоков, старые записи должны из списка/очереди удаляться иначе их накопится очень много.
S>Полагаю, что с этого надо было начать.
А>>решение на Dictionary вижу примерно следующее.
А>>
S>Вообще говоря это решение обладает недостатками: S>*) записи не удаляются
так их и не нужно удалять, их всегда ровно 10000. Просто старые перезаписываются новыми а не вставляются/удаляются.
S>*) синхронизация отсутствует как класс
ну я не стал загромождать код синхронизацией тут как бы главное алгоритм очереди
S>*) при добавлении очередного элемента и одновременном выполнении GetMeasures неминуемо исключение
это из п.2. и следует поставить lock{} большого труда не составит
S>*) записи не упорядоченны и берутся не последние
записи как раз упорядочены по Index в порядке добавления, допустим index текущий = 5000, соотвественно запрос выберет с 5001-10000 и сделает union с 1-5000 записи — получится список в хронологическом порядке — ему делается reverse().
Но в общем мне понравилось обычное решение с list.Insert(0,...) и list.RemoveAt(1001) его и буду использовать с большой вероятностью
Re[7]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, samius, Вы писали:
S>>Вообще говоря это решение обладает недостатками: S>>*) записи не удаляются А>так их и не нужно удалять, их всегда ровно 10000. Просто старые перезаписываются новыми а не вставляются/удаляются.
С чего бы это они перезаписываются?
S>>*) синхронизация отсутствует как класс А>ну я не стал загромождать код синхронизацией тут как бы главное алгоритм очереди
S>>*) при добавлении очередного элемента и одновременном выполнении GetMeasures неминуемо исключение А>это из п.2. и следует поставить lock{} большого труда не составит
S>>*) записи не упорядоченны и берутся не последние А>записи как раз упорядочены по Index в порядке добавления, допустим index текущий = 5000, соотвественно запрос выберет с 5001-10000 и сделает union с 1-5000 записи — получится список в хронологическом порядке — ему делается reverse().
Записи в словаре хранятся не в порядке вставки.
А>Но в общем мне понравилось обычное решение с list.Insert(0,...) и list.RemoveAt(1001) его и буду использовать с большой вероятностью
Сдвиг на каждое добавление? Так чем Queue-то не устроил?
Re[8]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 21:44
Оценка:
Здравствуйте, samius, Вы писали:
S>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, samius, Вы писали:
S>>>Вообще говоря это решение обладает недостатками: S>>>*) записи не удаляются А>>так их и не нужно удалять, их всегда ровно 10000. Просто старые перезаписываются новыми а не вставляются/удаляются. S>С чего бы это они перезаписываются?
ну посмотри алгоритм внимательно там значение currentItem бегает по кругу в пределах 0-9999
if ( currentItem >= queneCapacity )
{
currentItem=0;
}
quene[ currentItem ] = new MeasureData( p1, p2, p3 );
currentItem++;
соотвественно словарь сначала забивается 10000 элементами и больше уже не растет.
S>>>*) записи не упорядоченны и берутся не последние А>>записи как раз упорядочены по Index в порядке добавления, допустим index текущий = 5000, соотвественно запрос выберет с 5001-10000 и сделает union с 1-5000 записи — получится список в хронологическом порядке — ему делается reverse(). S>Записи в словаре хранятся не в порядке вставки.
Ну вот это засада если так.
А>>Но в общем мне понравилось обычное решение с list.Insert(0,...) и list.RemoveAt(1001) его и буду использовать с большой вероятностью S>Сдвиг на каждое добавление? Так чем Queue-то не устроил?
Ну я так понял что оно не двигает реально..может там связи обычные — но работает очень шустро. Проверил на 100000 записей что в 10 раз больше чем мне нужно — задержка всего 90 микросекунд.
Re[4]: Очередь фиксированного размера с вытеснением старых
От:
Аноним
Дата:
18.01.11 21:50
Оценка:
D>>>Не совсем понятно, почему не подходит обыкновенный List<>?
А>>Вот блин. Оказывается он ничуть не тормозной А>>Вполне шустро работает. Меньше миллисекунды..196 тиков всего. А>>А он не двигает все элементы при удаленни чтоли ? S>Двигает. А Queue — нет.
Ну даже если и двигает то очень быстро..намного быстрее чем я ожидал.
Quene недостаток в получении "перевернутого списка" , с list переворачивать не придется
и все решение сводится для вставки
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, samius, Вы писали:
S>>Здравствуйте, Аноним, Вы писали:
А>>>Здравствуйте, samius, Вы писали:
S>>С чего бы это они перезаписываются?
А>ну посмотри алгоритм внимательно там значение currentItem бегает по кругу в пределах 0-9999
А>соотвественно словарь сначала забивается 10000 элементами и больше уже не растет.
Да, проглядел
S>>Записи в словаре хранятся не в порядке вставки.
А>Ну вот это засада если так.
А>>>Но в общем мне понравилось обычное решение с list.Insert(0,...) и list.RemoveAt(1001) его и буду использовать с большой вероятностью S>>Сдвиг на каждое добавление? Так чем Queue-то не устроил? А>Ну я так понял что оно не двигает реально..может там связи обычные — но работает очень шустро. Проверил на 100000 записей что в 10 раз больше чем мне нужно — задержка всего 90 микросекунд.
Дак двигает реально, без вариантов двигает.
Re[5]: Очередь фиксированного размера с вытеснением старых
Здравствуйте, Аноним, Вы писали:
D>>>>Не совсем понятно, почему не подходит обыкновенный List<>?
А>>>Вот блин. Оказывается он ничуть не тормозной А>>>Вполне шустро работает. Меньше миллисекунды..196 тиков всего. А>>>А он не двигает все элементы при удаленни чтоли ? S>>Двигает. А Queue — нет.
А>Ну даже если и двигает то очень быстро..намного быстрее чем я ожидал. А>Quene недостаток в получении "перевернутого списка" , с list переворачивать не придется
Это лишь вопрос с какой стороны пробегать по результату.
А>и все решение сводится для вставки А>
Здравствуйте, Аноним, Вы писали:
А>>>Вполне шустро работает. Меньше миллисекунды..196 тиков всего. А>>>А он не двигает все элементы при удаленни чтоли ? S>>Двигает. А Queue — нет.
А>вот кстати решил провести тест, получилось
А>Quene Time:00:00:03.3552024 А>List Time:00:00:00.5903732
А>т.е. с Quene в 6 раз медленнее из-за необходимости Reverse()
А>если Reverse() убрать то получается чуть быстрее листа
А>Quene Time:00:00:00.3937243 А>List Time:00:00:00.5932789
А>
А> cnt += quene.ToArray().Reverse().Count();
А>
Так работает вровень, а то и быстрее:
var array = quene.ToArray();
Array.Reverse(array);
cnt += array.Count();
250005000
Quene Time:00:00:00.6969832
250005000
List Time:00:00:00.7490250