Как стать автором
Обновить
11
0
Иван @xXxVano

Пользователь

Отправить сообщение

Выскажу непопулярное мнение.


Конечно культуру за один день такие запреты не изменят, но как известно дорогу осилит идущий.
Работы по отсеву звонков/встреч для арендодателей прибавиться и вероятно не все настолько принципиальны, что бы отказываться от арендатора, который подходит по всем остальным параметрам. А со временем этот критерий и вообще может изжить себя.


К тому же Циан скорее всего хочет расширить свой рынок за пределы Москвы/России. А в Европе/Штатах за отсутствие подобного рода ограничений можно если не на штрафы, то на "народный гнев" очень даже хорошо попасть.
Да и гугл/аппл могут вполне себе ввести ограничения для приложений, допускающих открытый расизм, особенно с учётом текущей повестки на западе.

Помереть может, но пробить кожух от этого не должен. Кожух должен быть достаточно прочным что бы это выдержать.
Так то и случайный грузовик на полном ходу может не справиться с управлением и запарковаться в контейнер с запущенным реактором.

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


На консолях даже без кросс-плея игроки вайнят на других и обвиняют их в том что они вместо геймпада подключили клаву с мышкой. При этом в половине случаев с другой стороны игрок с точно таким же геймпадом, но просто более скиловый.


При кросс-плее матчмейкинг обычно старается матчить игроков с геймпадами отдельно от игроков с мышками. Так же как и отдельно от игроков с телефонов.


Что качается именно ассиста, то он просто значительно повышает комфорт игроков с геймпадом, но это совсем не тоже самое что автоэйм, автор как раз раскрыл разницу. Автоэйм и на мышке повышает эффективность. А эймассист достаточно часто мешает.

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


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


В шутерах кроме этого есть и другие скилы (позиционирование игрока, реакция, знание карты, etc). И вот как раз на них и делается упор и за счёт них получается фан.

Нет. Обратите внимание: я этим дал гарантию на корректность инварианта контейнера (size не может быть отрицательным), но не на index, который таки тут проверяется.

Вы сказали компилятору — считай что size не отрицательный. Но на практике это может быть не так. И вот в случае с C++ вы получите UB. А в случае с тем же дотнетом, компилятор вам не поверит (поэтому так сказать и нельзя). А если вы сделаете такой каст к (uint), то он выполнит выполнит 1 проверку вместо 2-х. Но в случае если вы ошибётесь, то получите вполне себе определённое поведение — исключение.


На мой взгляд и то и другое хак. Да, в одном случае — что бы склеить проверку в 1, в другом что бы подсказать сделать это компилятору.


Но и там и там это лишнее действие которое нужно делать.


CLR и сейчас беззнаковых нет? Вам наличие беззнаковых не гарантируется (или в последнюю пару лет добавили?) Думаю, поэтому в интерфейсах стандартных классов int, а не uint.

Не очень понимаю о чём вы. В стандарте CLI они есть. В типах BCL они есть. В C# они есть.


Если речь про методы, помеченные CLSCompatible, то среди них нет не только беззнаковых типов, но например ещё и операторов. Это сделано для того что бы на CLI можно было реализовывать языки, которые не поддерживают беззнаковые типы (например Java) или операторы (например VB.Net).


А коллекции юзают размер в int'ах как раз из-за Java, что бы можно было её поверх заимплементить. Что оказалось, к счастью, никому не нужным.


Что мне даст передача int вместо, условно говоря, int_range<0,999>

Я не понимаю зачем вам int_range<0,999>? Что вы от этого получите? Ограничите бизнес домен? Если так, то это очень слабая конструкция для этого. А как домен чётных чисел задать? А 0-99 кроме 1-цы? И всё что за пределами ограничений ренжа.


По факту для реализации бизнес требований нужны полноценные типы. И вы их можете имплементировать. А вот машинные нужны только для того что бы указывать сколько памяти использовать под тот или иной типа. Ну и минимальный набор правил арифметики.


Но ещё раз, об этом можно много рассуждать и много чего придумать. Не готов сейчас развивать эту тему.


У нас базовый контекст всей темы — C++.

Я как раз отвечал предыдущему комментатору на другой аргумент — что Java отказалась от беззнаковых типов.


Мой поинт в том что беззнаковые типы позволяют делать многие оптимизации при работе с размерами контейнеров. И на примере C#, как языка в котором есть беззнаковые типы, но в качестве размеров контейнеров выбраны именно знаковые, показал что это приводит к костылям при реализации стандартной библиотеки, в угоду оптимизациям.

Похоже на слабость логики кодогенератора дотнета. Вот я на C пишу:

Ага, и весь хак в этой сточке: if (arr->size < 0) { __builtin_unreachable(); }
Вы явно сказали компилятору что уверены, что такого не будет, а иначе опять же UB. И конечно после этого компилятор может забить на знаковость. Только вот этот хак нужно будет писать по всему коду. В других языках такой опции нет (т.к. UB не в почёте) и поэтому такое написать очевидно нельзя.


А вот если убрать это строку, то компилятор сгенерит идентичный код с 2-мя проверками.


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

Безусловно это так. И подобные оптимизации могут приносить значительный прирост скорости. Но при работе с размерами контейнеров они встречаются существенно реже чем проверки границ.


А если говорить про менеджед языки, то такие проверки требуются вообще во всех функциях работы с размерами контейнера. И везде приходится эти хаки расставлять.


уже упоминал, последствие слабости самой системы типов — в том, что она сводит до стандартных машинных типов и не обеспечивает проверку

Это большая тема для обсуждения, не хочется её трогать. Там и до функциональных языков недалеко. Если коротко, то привязка к машинным типам имеет смысл. Поверх можно что угодно накрутить, хоть и не так эффективно как можно было бы. Тот же Index или Range в .Net.


Почитайте дискуссию — там ещё много аргументов (в обе стороны). Вот, кстати, по поводу размеров — одна из первых реплик там:

Ага, спасибо поглядел. В общем я согласен что с uint бывает неудобно работать. Но со временем вырабатываются паттерны избегать таких подходов. Хотя возможно для новичков это вызывает сильное неудобство, это тоже аргумент.

для беззнаковых, даёт возможность таки делать большое количество оптимизаций вида: x+1>x заменить на true; a+1>b+1 заменить на a>b;

Это потому что стандарт C++ обозвал переполнение знакового числа — UB. В других языках такого нет, а раз переполняться знаковый тип валидно, то такие оптимизации будут давать неверный результат.


Но даже если смотреть на C++, то если у вас написан код if (x + 1 > x) ..., то выглядит так что не оптимизатор его должен улучшать, а программист, т.к. сам по себе он контринтуитивный и вводящий в заблуждение. В то же время при работе с индексами и размерами приходится постоянно проверять на > 0, что приводит к дополнительному коду (что можно упростить через каст к (uint)).


Это как раз к вопросу о диапазонах значений. В конкретном случае за счёт того, что размер коллекции уже ограничен int.MaxValue (а с чего бы это, если с беззнаковыми якобы лучше???), можно делать такой хак.

Я там ниже уже отвечал на этот вопрос. Пример выбрал не очень удачный, т.к. там 2 хака юзается. Речь была про то что компилятор сам не имеет права заменить / 2 на >> 1 из-за того что тип значимый и что бы явно сказать что мы согласны, приходится к (uint) кастить.


Но на самом деле подобных мест в BCL много. Например тут или тут
Это способ сэкономить на проверке что index > 0. Которой могло бы вообще не быть нужно делать.

Они удовольствие получают не от того что они/программа играет круто, а от того что они унижают других. Как тролли. В этом и есть вся проблема. А ещё местом в рейтинге или значением K/D похвастаться можно. Или в чате поунижать оппонента после победы.


В общем они получают удовольствие не традиционным способом.

Да нет, я смотрю нормально. То что вы расписали я вижу, о чём и указал в предыдущем комментарии.


Только вы упускаете что std::distance() не вызывается внутри цикла. То есть last - first не вычисляются на каждой итерации, как это сделано в Java и .Net. И место что бы допустить столь популярную ошибку (hi + lo) / 2 тут нет.


В любом случае к изначальному вопросу отношения это не имеет.


Вот только в этой реализации есть проблема: std::distance() может оказаться отрицательным из-за переполнения.

И в чём же проблема? Где lower_bound отработает неверно в этом случае?

По вашей ссылке это first + (last – first) / 2, причём арифметика знаковая, без всяких приведений.

А я вот такого кода не вижу. На первой итерации будет выполняться что то похожее, но как минимум вы забыли проверку while (count > 0) в промежутке. И именно благодаря ей, компилятор может гарантировать что count положительный и можно выполнять shr.


Но ведь ничто не мешает в коде вместо (hi – lo) / 2 написать (hi – lo) >> 1 (для двоичного поиска не принципиально, в какую сторону идёт округление) и получить одну инструкцию

С этим никто и не спорит. Руками вы можете написать что угодно. И в Java ровно так и сделали. Но вот компилятор за вас это не напишет. И не сделает ещё кучу оптимизаций, которые мог бы сделать, если бы знал что переменная точно > 0. А беззнаковый тип только это и гарантирует.


Так что использовать беззнаковые типы везде где можно, с точки зрения производительности очень даже оправдано. И Java, в которой нет такой возможности, тут вовсе не причём.

Нет, в .NET такая оптимизация возможна только по причине того, что размер контейнера ограничен именно знаковым типом (т.е. сумма lo + hi не вызывает переполнения).

Я про использование uint vs int вообще, а не только про данный конкретный случай. Тут оба трюка используются. Но даже если отбросить возможность каста к uint (как в Java), здесь был бы код lo + (hi - lo >> 2), а не lo + (hi - lo) / 2). А в c++ lower_bound вообще по другому организован (подробности тут)


Этот пример просто вспомнился быстрее всего. Но каст к uint часто используется даже в проверке предусловий, что бы подсказать облегчить JIT-у дальнейшую оптимизацию.


Не может такого быть. В x86/x64 есть как операция SHR, так и SAR.

Очень даже может. Для этого нужно понять что же сделает следующий код (что будет в eax):


mov eax, -1
sar eax, 1

или просто const int a = -1 >> 1;


После этого будет ясно, почему JIT генерирует вот такой код (пруф):


mov eax, edx
shr eax, 0x1f
add eax, edx
sar eax, 1

P.S.: И да, я знаю что какой-нибудь gcc или clang заиспользуют ASR в этом простом случае, но это всё же немного другое.

Вероятно потому что Java пытается обеспечить кроссплатформенность. И существуют платформы, на которых процессор может не поддерживать беззнаковые типы (но это не точно).
В то же время C++ вообще не парится по поводу кроссплатформенности и отдаёт это на откуп программисту.


Беззнаковые типы позволяют делать значительно больше оптимизаций. Особенно это актуально для всяких размеров контейнеров. Например тот же .Net, хотя и имеет все размеры в знаковых типах, внутри системной либы (BCL) часто делает каст к uint только для того что бы JIT мог производить оптимизации (например тут).


Банально value / 2 нельзя заменять на value >> 2, если тип знаковый, JIT ещё доп инструкцию делает, что бы знаковый бит сохранить.

Проперти в обоих случаях заинлайнились. В случае с forach же нет вызова get_Current() у итератора.

Я бы тоже на это рассчитывал, но потом проверил и оказалось что jit оставил не виртуальный вызов.


Увидеть можно если включить отображения asm-а на sharplab.io в той ссылке что я скидывал.


То есть такая возможность есть, но на практике это не так. Возможно в последующих версиях (или в .Native AOT) завезут ещё оптимизаций)

Итерирование по List<T> безусловно быстрее чем итерирование по абстрактному IEnumerable<T>. Кроме создания лишней обёртки, IEnumerable приводит к 2 лишним виртуальным вызовам на каждую итерацию (вместо 1-го не виртуального), что может оказать намного более значительный результат при большом количестве элементов.

Хотя самым быстрым вариантом для листов сейчас выглядит всё же обычный for, за счёт отсутствия лишнего call-а метода MoveNext. Забавно что для листов JIT не выкинул баундинг чек за предел цикла, как он это делает с массивами.

P.S.: Но вообще на практике я думаю что разница между for и foreach по List<T> будет столь ничтожна что её даже в молотилке цифр будет не разглядеть.

Конечно, потому что foreach первым делом его в локальную переменную сохранит, а for нет. Такого же эффекта можно добиться если самому сохранить его в локальную переменную.

Код на ассемблере смотреть не обязательно, можно переключиться в C# вид, что бы наглядно увидеть разницу.

Но опять же, в случае с листом всё наоборот, т.к. лишний call стоит дороже.

Это не совсем так. В случае массивов, для foreach компилятор просто генерит код как для обычного for. Но для листов и других абстракций это не так (по крайней мере сейчас на текущем компиляторе).

Заглядывать в IL в этом случае даже не обязательно, можно посмотреть результат и в виде C# кода на sharplab.io (пруф)

Если я правильно понимаю то "Выделенная память" это просто виртуальная память, то есть адресное пространство, которое операционка вам зарезервировала под указатели, которые потом будут смаплены в реальную физическую память.

Если это так то на 64-х битной операционке крайне сомнительно что бы она у вас могла закончится, даже с учётом что под указатель не все 64 бита используются, там всё равно неприлично большие числа.

И я не могу ничего запустить тяжелого, приложения ругаются что не хватает памяти, я повторю еще раз у меня свободно 30 гб физической памяти

Что то подсказывает что проблема в этом чём то тяжёлом. Возможно аллоцирует большие блоки непрерывной памяти например. И тогда уже проблема будет в фрагментации. Для решения этого есть кстати всякие геймерские тулы. Хотя за их эффективность не поручусь.

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


fun sum() : Int {
    return 1 + 2 + 3 + 4 
        + 5 + 6
}

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность