Здравствуйте, Sinix, Вы писали:
S>Нет. Учить матчасть — это в том числе самостоятельно решать проблемы, а не обзывать других индусами, т.к. они не сделали это за вас. Там ещё много всего, но начать стоит именно с этого.
Давайте я прибегну к аллегории, может быть так вам станет яснее.
Представьте себе что вы архитектор. Не московский c#-"архитектор" полугомосексуал в прозрачном свитерке, а самый настоящий американский архитектор 20-30-х годов 20-го века. Словно Хэнк Риэрдан в архитектуре (не буду вас утомлять деталями, кто этот персонаж). И вам нужно спроектировать Эмпайр-Стейт-Билдинг. В берете чертежный набор чтобы сделать свою работу и что же вы видите? Циркули все погнуты, сломаны или недоделаны, линейки все косы и кривые, а карандаши не чертят. Вы в гневе идете к производителю и говорите — это что такое? У меня работа стоит! А производитель вам отвечает — вам нужно выпрямить все циркули самому, выточить все новые линейки самому, а карандаши ну зачем они вам? Ведь люди в Азии рисуют углем вы то чем хуже? Вы им бросите в гневе — ваш инструмент гавно! А они вам "Учить матчасть — это в том числе самостоятельно решать проблемы, а не обзывать других индусами, т.к. они не сделали это за вас. Там ещё много всего, но начать стоит именно с этого.".
А небоскреб из стекла и стали все еще не построен потому проектировать углем как-то знаете неудобно.
Вы поймите, я же не прошу какого-то чуда. Ну в java же все есть. Неужели даже скопировать нормально не могут?
S>Кэп #2: как самостоятельно напишете что-то сравнимое — приходите. Там кроме пафоса с апломбом ещё знания нужны, вот незадача
Да нет тут никакого пафоса и апломба. Просто потому что сделать лучше чем сейчас в вашем любимом framework может любой нормальный программист. Здесь нечем гордится. Это обыденность, на которую просто придется убить день. Не rocket science, совершенно обычная задача. Правда отчего MS на это шесть лет потребовалось. Вот незадача. Хотя чем я удивляюсь в очередной раз?
Здравствуйте, mapnik, Вы писали:
M>Давайте я прибегну к аллегории, может быть так вам станет яснее.
Кривая аналогия. Проблема не в инструментах.
Проблема в том, что вы сели в капитанское кресло аэробуса и по громкой связи требуете от общественности боинг. Дескать, летать нельзя: штурвал утратили, ручку шасси сломали, форточки не те, а РУД вообще страшно сказать — автомат. Переучивайтесь.
Ну, или не лезьте туда, куда душа не лежит. Ругаться-то зачем?
M>Вы поймите, я же не прошу какого-то чуда. Ну в java же все есть. Неужели даже скопировать нормально не могут?
В шарпе тоже есть. Только вы просите точный аналог явы, иначе типа не считается.
M>Да нет тут никакого пафоса и апломба. ... Это обыденность, на которую просто придется убить день.
Я ж не зря писал про что-то сравнимое. Посмотрите на устройство TryAddInternal/TryUpdate, особенно на веточки с s_isValueWriteAtomic==false и FEATURE_RANDOMIZED_STRING_HASHING и не несите чепухи. Про нюансы с tables/nodes даже начинать не буду.
Здравствуйте, mapnik, Вы писали:
M>Именно поэтому тема находится в СВ.
Место этой теме — в помойке, ты себя слишком высоко оцениваешь.
T>>Заменить Hashtable на Dictionary<int, float> M>Хотя ваш совет абсолютно правилен, этого нельзя сделать по некоторым причинам .
Да вообще никаких причин нет — это ты пришёл сюда с апломбами жабиста и пытаешься с какими-то искусственными ограничениями обыграть .NET;
Твои цели вообще непонятны — ты не проблемы решаешь, а именно понтуешься — смотришься как быдлятник, которому в табло мало засвечивали.
Ты уясни одну вещь: нам вообще на тебя на****ть — будь ты хоть лисповец или смоллтоковец. Хочешь решать проблемы на C# — подымай реальную задачу и спрашивай.
M>Хочу услышать их мнение .
Не хочешь, просто тупо гнёшь "моя жабка круче дотнета". Я с тобой даже спорить не буду, но ты КАК ТРОЛЬ тратишь время людей на препирания по бестолковейшему вопросу.
Нужен хэш — бери Dictionary и не выёживайся. И только когда у тебя возникнут _реальные_ проблемы с производительностью, тогда пересматривай решение (возможно, что и хэш — такой же бестолковый выбор, как и вся твоя тема).
За годы писания на дотнете я вообще никогда не сталкивался с тем, что грамотно выбранная коллекция мешала производительности — учись, жабкин!
Здравствуйте, mapnik, Вы писали:
M>Господа, M>Есть следующий (сильно упрощенный код ввиду публичного рассмотрения) c# код M>Как видите преимущество в производительности JVM в данном коде примерно на порядок (в 10 раз).
M>Что я делаю не так? Может быть где-то ошибка в коде? Если нет, то как ускорить C# код хотя бы до уровня JVM? M>Надеюсь на помощь господ, умудренных опытом в C#. Спасибо
Я мало умудрен опытом C#, поэтому вопрос не про язык программирования.
Зачем тебе большая скорость добавления в Hash? Может лучше взять список с константным добавлением? Ты бы определился с данными, что у тебя чаще вставка или поиск, и нужен ли тебе константный поиск.
Для меня твой вопрос звучит так: Гвоздь лучше забивается плоскогубцами чем отверткой. Действительно ли плоскогубцы лучше чем отверка? Если нет то как правильно забивать гвоздь отверткой?
Здравствуйте, Igore, Вы писали:
I>Зачем тебе большая скорость добавления в Hash? Может лучше взять список с константным добавлением? Ты бы определился с данными, что у тебя чаще вставка или поиск, и нужен ли тебе константный поиск.
Вставка в Hash table в лучшем случае O(1), в худшем O(n).
Ну я надеялся что программисты из MS нашли хорошую хэш-функцию и hashtable не вырождается в LinkedList сразу же.
Впрочем глядя на шарепоинт-программистов с блестящими глазами я уже в этом не уверен .
I>Для меня твой вопрос звучит так: Гвоздь лучше забивается плоскогубцами чем отверткой. Действительно ли плоскогубцы лучше чем отверка? Если нет то как правильно забивать гвоздь отверткой?
Тема чистый троллинг, я согласен. Но как весело смотреть на всю это "разгневанную секту" c#-программистов. Тест который я привел просто не укладывается в их промытые маркетингом мозги. Have a fun!
* Первый тест был на java1.8.0_05/win64 — java уступила в скорости неоптимальной версии C# Я подумал: jre не та...
* Второй тест на последней версии доступной с сайта — в некоторых итерациях почти догоняет оптимизированню версию, но в основном всё равно уступает неоптимальной — повидимому сказывается работа GC
(посмотреть можно тут: http://rsdn.ru/forum/flame.comp/6096755.1
) Я подумал: может дело в винде?...
* Третий тест — debian 7.8 wheezy/openjdk 1.7 (увы, это единственное что доступно из репозитория) — результат аналогичен первому тесту.
В принципе возможно (потому что у меня нет возможности это проверить, ибо лень), что oracle java 8 последней версии да на линухе покажет заявленные результаты... но слабо верится.
Какая-то черешка того... в принципе быстрый уход из темы её автора даже намекает какая именно
Здравствуйте, Sinix, Вы писали:
S>>Какая-то черешка того... в принципе быстрый уход из темы её автора даже намекает какая именно S>Не надо спорить. Автор откровенно троллит.
Троллить это нормально, а вот делать это с очень... противоречивыми данными как минимум непорядочно.
Здравствуйте, Somescout, Вы писали:
S>Троллить это нормально, а вот делать это с очень... противоречивыми данными как минимум непорядочно.
Скорее всего данные реальные, фаза луны так сложилась. Как пример — недавние похожие наезды на шарп в этом топике
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Somescout, Вы писали:
S>>Троллить это нормально, а вот делать это с очень... противоречивыми данными как минимум непорядочно. S>Скорее всего данные реальные, фаза луны так сложилась. Как пример — недавние похожие наезды на шарп в этом топике
и дальше по ветке. Без автовекторизации (которую уложить в жёсткий лимит JIT — задача та ещё) — баш на баш.
Не уверен. Дело в том что подобная оптимизация по идее делается JIT'ом, а значит первые проходы по циклу должны быть дольше, чем последующие. Что видно из натестированного мной. Я бы вообще предположил, что в одной из версий jre8 добавили оптимизацию, которая специализирует коллекции (и словари) если там используются только примитивные типы — т.е. делается то же самое что при переходе на generic Dictionary в C#, но без гарантий, зависимо от jit'а.
Строго говоря — нет.
В Hashtable нет ни volatile read/write, ни memory barriers, т.е. вполне возможно зачитка по уже имеющемуся ключу еще не вставленного значения или же наоборот: зачитка ключа от уже удалённого значения.
Т.е. ситуация, когда мы не можем найти элемент, который "только что добавлен из другого потока", или нашли и прочитали элемент, который "уже удалён другим потоком" — это вполне нормальный сценарий для конкурентного доступа. Но когда мы по валидному ключу читаем невалидное значение, то это уже натуральный ууупппсс. ))
M>2) Я пробовал прогонять код для более короткого цикла (напр. 100000) и clr и jvm имеют одну производительность. Такое ощущение что CLR GC не справляется. Это также подтверждается вызовом GCSettings.LatencyMode на LowLatency. Цифры сразу взлетают вверх.
Это боксинг. Твоя псевдопотокобезопасность Hashtable зиждется на том, что ключи и значения в таблице представлены типом-ссылкой, чтение и запись которых атомарны на поддерживаемых CRL платформах. В общем же случае как в Dictionary<> в дотнете или аналогичном решении на Java, где ключ или значение не влезают в машинное слово — никаких потокобезопасных решений без специальных для этого техник (типа read/write lock, даже пусть их ligh-варианта на спин-локах) нет и быть не может. Всё, что нельзя записать/прочитать через Interlocked.Exchange (или его аналог) — всё идет мимо кассы.
Кароч, сама постановка задачи изначально ошибочна — нельзя требовать того, что быть не может.
Здравствуйте, vdimas, Вы писали:
M>>1)Hashtable is thread safe. V>Строго говоря — нет. V>В Hashtable нет ни volatile read/write, ни memory barriers, т.е. вполне возможно зачитка по уже имеющемуся ключу еще не вставленного значения или же наоборот: зачитка ключа от уже удалённого значения.
Открываем System.Collections.Hashtable декомпилятором и видим:
private volatile int version;
private volatile bool isWriterInProgress;
Опять говоришь о том, что не знаешь.
Не надоело позориться?
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
M>>>1)Hashtable is thread safe. V>>Строго говоря — нет. V>>В Hashtable нет ни volatile read/write, ни memory barriers, т.е. вполне возможно зачитка по уже имеющемуся ключу еще не вставленного значения или же наоборот: зачитка ключа от уже удалённого значения. WH>Открываем System.Collections.Hashtable декомпилятором и видим: WH>
Да, в дотнете volatile означает барьеры памяти. Думал, как в плюсах это является инструкциями только компилятору.
Барьер не полный, в случае с дотнетом:
Термин volatile read означает чтение памяти в сочетании с созданием accure fence.
Accure fence гарантирует что инструкции, стоящие после барьера, не будут перемещены в позицию до барьера.
Обратное гарантируется Release fence, т.е. volatile write.
Посмотрел еще раз внимательнее на чтение:
private bucket[] buckets; // без volatile
...
bucket[] lbuckets = buckets;
...
do
{
int currentversion;
int spinCount = 0;
do {
// this is violate read, following memory accesses can not be moved ahead of it.
currentversion = version;
b = lbuckets[bucketNumber];
...
} while ( isWriterInProgress || (currentversion != version) );
Т.е. операция b = lbuckets[bucketNumber] является независимой от обращения к полям isWriterInProgress и currentversion, т.е. может произойти уже после их чтения. Барьер по чтению как раз это разрешает.
После этого while идет проверка на то, что найденный ключ b.key соответствует искомому.
В момент чтения b = lbuckets[bucketNumber] без всяких барьеров можно прочитать в поля bucket значения из памяти в произвольном порядке, например прочитать в b.val null, в то время как b.key и b.hash_coll будут еще валидными.
Здравствуйте, vdimas, Вы писали:
V>В момент чтения b = lbuckets[bucketNumber] без всяких барьеров можно прочитать в поля bucket значения из памяти в произвольном порядке, например прочитать в b.val null, в то время как b.key и b.hash_coll будут еще валидными.
В этом случае сработает вот это условие
isWriterInProgress || (currentversion != version)
И значение будет считано ещё раз.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, mapnik, Вы писали:
M>Я не совсем точно сформулировал свой вопрос. Я хотел бы понять у C# и шарепоинт-программистов, почему clr так легко проседает на таком простом кусочке кода по отнашению к JVM . Именно поэтому тема находится в СВ. M>Хочу услышать их мнение .
Не совсем ясно, как ты хочешь получить разницу между clr и jvm, сравнивая __разные__ алгоритмы
Здравствуйте, mapnik, Вы писали:
M>Здравствуйте, Yoriсk, Вы писали:
Y>>Еще раз, по порядку: cравниваются реализации на Java и С#. Вы говорите, что реализация на HashMap, который thread-safe только в случае immutable на java вас устраивает, а на Dictionary на .net — нет. Поэому в Dictionary нужен ReaderWriterLock, а в HashMap, ... какая-то аналогичная конструкция на java(ReadWritLock?). Y>>Вот я и спрашиваю: а в чём, собственно, разница?
M>Ок, по порядку: M>1) Меня не устраивает perf для Hashtable на c#. По моим данным она в 10 раз ниже аналога на java
Краткий пересказ того, что ты не смог правильно перевести:
1 Hashtable не является аналогом HashMap
2 Близким аналогом HashMap является Dictionary<>
Здравствуйте, WolfHound, Вы писали:
V>>В момент чтения b = lbuckets[bucketNumber] без всяких барьеров можно прочитать в поля bucket значения из памяти в произвольном порядке, например прочитать в b.val null, в то время как b.key и b.hash_coll будут еще валидными. WH>В этом случае сработает вот это условие WH>
Я как раз указал на то, что коль содержимое this.buckets не является volatile, а операция b = lbuckets[bucketNumber] независима по данным с isWriterInProgress || (currentversion != version), то процессор имеет полное право эти операции переупорядочить. Посмотри внимательно еще раз. Обращение к isWriterInProgress и currentversion идет по чтению:
Accure fence гарантирует что инструкции, стоящие после барьера, не будут перемещены в позицию до барьера.
Но обратное разрешено.
Т.е. косяк есть и не срабатывает он лишь по той причине, что в текущих процах x86 и AMD64 нет разделения на Release fence и Accure fence, т.е. барьер всегда только один — полный Strict fence (оно же std::memory_order_seq_cst в С++11). Зато в Итаниуме и PowerPC барьеры разные.