All streams
Search
Write a publication
Pull to refresh
1
0
Анатолий @iRumba

Программист C#

Send message
Откуда такой максимализм? Такое ощущение, что Вы читаете комментарии оратора, на которые читаете, по диагонали, вырезая слова из контекста.
Это же проект для тренировки. Позже окажется, что добавив немного кода, можно получить сеть поумнее. И так по нарастающей. Я видел, как такие вот «программулины для примера» превращаются в коммерческое ПО. Вот только оптимизация уже отнимает больше сил и времени. Поэтому изначально лучше не сокращать код жертвуя производительностью, особенно когда он не упрощается, а именно сокращается. Неужели linq тут выглядел бы понятнее? Ну разве что чуть-чуть.
Даже такой простой код написан так, что и комментарии не помогают читать его не возвращаясь несколько раз назад. :(

Я не перфекционист, но блин… )
Можно сократить в linq и сеть потеряет в производительности.
Подтер за собой )
В голосовании нет варианта «Сталкивался, но мне до лампочки» :)
Нет, не ломает. Желательно скриншот и объяснение.
Фактически, то же самое предложил skyramp только без таймера. Математическая модель та же. Вместо таймера мы просто замеряем дельту времени между запросами при выполнении CanExecute(). То есть у вас происходят вычисления каждые Х мс, а без таймера просто при запросе эти вычисления умножатся на на количество мс между запросами.
Так вот такое решение на том же самом тесте, на котором я тестировал свое, пропустило 8 задач вместо 6. Все дело в том, что запрос при таком подходе оценивается как усредненное значение времени. Это будет работать только в том случае, если запросы будут поступать каждые s / rps секунд. То есть такой подход ломает ограничение. Более того, он позволит пользователям обойти его намеренно.
Ваша реализация ломает ограничение на количество операций в секунду.
Что я должен передать в конструктор в качестве perInterval?
Но я так понимаю в CanExecute() вы только добавляете слепок времени? А очистка происходит по таймеру?
Под скоростью в данном случае я имею ввиду время выполнения CanExecute()

Требования — она должна выполняться максимально быстро. Если в моем решении она выполняется быстрее, чем в вашем, вы проигрываете.

Я много с чем не знаком в платформе .NET. Как и вы, думаю. И если бы данная коллекция могла бы мне помочь, я бы с ней познакомился. Потому что я, прежде чем «изобретать велосипед», прочитал описание всех коллекций, которые смог найти. На некоторых останавливался чтобы изучить подробнее. И ничего мне не подошло.
Да хватит пихать сюда таймер! Я уже описал пробелмы таймера. Если ThreadPool не найдет свободного потока, то таймер будет опаздывать! И это при том, что частоты 1 раз за 1мс и так недостаточно!
Очень замечательно. А теперь предложите решение на основе BlockingCollection, которое не проигрывает по скорости.
Я уже где то отвечал на это. У меня задача не стандартная и стандартные средства тут не годятся.

Экономия на выделении памяти под элементы — экономия на спичках.

Я не экономлю на памяти как раз.

Никто не запрещает перед основной работой сразу создать нужное количество элементов.
Да, я именно так и делаю.

Кстати, не очень понятно, зачем в условии задачи привязка к количеству запусков в секунду. Очень похоже, что это переформулированная задача об одновременном существовании определенного количества объектов в нескольких потоках.
Есть API, некоторые функции для каждого пользователя ограничены количеством выполнений в секунду. Ограничение это взято из статистики. В итоге сервер успевает обработать все входящие запросы и пользователи не ждут в очереди, пока отработают куча ненужных запросов других пользователей, которые, кстати, могут так наспамить, что мало не покажется. А так им придется организовывать работу под ограничение. Ну и плюс это какая никакая защита от ddos.

Для таких вещей придуманы семафоры. В частности в шарпе есть модификация SemaphoreSlim, которая позволяет задать сколько именно потоков будут иметь параллельный доступ к ресурсу. И нет, писать код за вас я не стану. На MSDN отличный пример для SemaphoreSlim

Вы мне рассказываете о чем моя задача? Зачем? Я не писал изначально о ее предназначении, потому что это не имеет значения.
Зачем убирать Thread.Sleep()? у меня же запросы будут не сплошным потоком. Я же не файлы копирую :)
Между запросами в любом случае будет пауза. Хоть короткая, но будет.
Я не уверен, как в яве разруливаются потоки, но в .NET количество активных потоков не может превышать количество ядер процессора. Если потоков запущено больше, то они будут чередоваться (один уснул, другой проснулся). То есть если я запускаю таймер с интервалом 1мс и в системе запущено еще несколько потоков, то таймер может не проснуться вовремя, так как другие активные потоки могут надолго зависнуть и не отдавать эстафету системе (среде выполнения). Почему то мне кажется, что это ограничение железа и системы по-другому обойти проблематично и в яве все устроено так же.
В любом случае вы можете это проверить, запустив 100 потоков параллельно на цикл 1-100 с выводом счетчика и номера потока.

Но даже если таймер в яве работает точно как швейцарские часы, появляется просадка по точности. И точность эта 1мс. Хотя за 1 мс может быть выполнено довольно много запросов.

В моем коде на данный момент то же самое ограничение, но я легко могу его преодолеть, заменим штамп с ElapseMilliseconds на ElapsedTicks. Количество тиков за миллисекунду зависит от процессора и настроек системы. На моем домашнем (слабеньком) компе это значение равно около 300000. То есть точность будет максимальной (за 1 тик точно больше одной операции не будет выполнено).
Как то так.

А про AtomicInteger я не в курсе. В шарпе такого нет. Так что я не понимаю как это работает.
Покажите код вашего таймера
Или вы не привыкли замерять производительность вашего кода.
Стандартные инструменты подходят для большинства стандартных задач.

В моем случае задача не стандартная и стандартных инструментов без потери в производительности для нее нет. В первую очередь код должен соответствовать своей задаче, не выполнять ничего лишнего (особенно там, где каждый тик на счету), и только во вторую должен быть понятным.

Поток будет спать не 99,9% времени в данном случае. Хотя это зависит от его периодичности. Тут во избежание ошибок периодичность должна быть 1 такт в миллисекунду. И то этого мало, это урезает точность выполнения, когда за 1 миллисекунду происходит больше одного запроса. И кроме всего прочего таймер (в .NET по крайней мере) гарантирует выполнение не чаще, чем установленная периодичность, а вот реже вполне может. Значит точность будет еще ниже.

Но как обстоят дела на Java, уважаемый Senior Java Developer, я не знаю. тут вам виднее.

Information

Rating
Does not participate
Location
Томск, Томская обл., Россия
Date of birth
Registered
Activity