« first day (986 days earlier)      last day (2045 days later) » 

3:36 PM
@АндрейNOP, @VladD, а кто вообще должен эти контролы делать? Дизайнер или прогер?
 
@Bretbas подождем @VladD, мне, к сожалению, не доводилось пока работать в команде над WPF приложением.
Но мое мнение вы знаете - бизнесу не нужны рюшечки, ему достаточно стандартных контролов в 99% случаев
 
@АндрейNOP Но все же. Вот смотри. Я ща буду делать клиент для облака. Если оно будет со стандартными контролами аля Windows 98, что о нем скажут?:)
@АндрейNOP, все таки дизайн тоже имеет значение:)
 
@Bretbas почему это аля '98? Будет в стиле той ОС, в которой запущено
 
@АндрейNOP А все Ось почти похожи:)
 
@Bretbas ну в общем-то - да, если приложение какое-нибудь для молодежного контингента, типа мессенджеров и т.п., то дизайн имеет место быть. Если же приложение для "теток из бухгалтерии", то должно быть всё предельно интуитивно понятно и со штатным поведением и без рюшечек
 
3:46 PM
@АндрейNOP Это я согласен:)
 
@Bretbas лично мне важно удобство использования - гибкие настройки, минимум лишних действий, хоть я еще пока и отношу себя к молодежному контенгенту
 
 
2 hours later…
5:36 PM
@Bretbas Хихикс! Это хороший вопрос.
Я вот был на тренинге Майкрософт, они говорят вот что
Если у нас софтовая компания, то нужно иметь в ней
(1) дизайнеров, которые проектируют контролы,
(2) программистов, которые пишут код, и
(3) одного интегратора, который служит между ними мостом, и может как донести до дизайнеров хотелки программистов, так и донести до программистов, как же по замыслу дизайнера должен вести себя контрол.
Я вот таким интегратором проработал год. И скажу, что это непростая задача.
То есть дизайнер делает мокапы, желательно в Expression Design (чтобы можно было сконвертировать в XAML). А интегратор, тихонько матерясь про себя, приводит этот XAML в нормальный вид (убирает изменение размеров шрифта трансформациями и позиционирование маргинами, создаёт нормальную вложенность контейнеров и применяет layout manager, запрашивая детали поведения у дизайнеров)
 
5:57 PM
@vitidev @VladD что-то я не понял, о каких барьерах вы там спорили?
 
@VladD тут одно из двух. Либо этот барьер помешает JIT переставлять инструкции так же как он мешает это делать процессору - либо этот метод полностью бесполезен.
Поскольку он до сих пор не Obsolete - первый вариант правдоподобнее.
 
@PavelMayorov С этим я не спорю. Вопрос в том, как инструкции процессора соотносятся с командами C#. Т. к. компилятор может размазать команды C# по IL и по машинному коду тонким слоем.
Там у меня был пример с popcount
 
@VladD Может - но только между барьерами. Через барьеры инструкции размазываться не могут.
 
@PavelMayorov Хм. Вопрос в том, всегда ли можно ли так скомпилировать?
Ну и традиционно, есть ли гарантия в документации?
 
6:07 PM
@VladD Да, всегда. Всегда есть вариант откатиться на построчную компиляцию.
 
@PavelMayorov Хм. Дайте переварю эту мысль.
Окей, переварил, согласен.
Тогда вопрос о гарантиях, хотя, конечно, по факту компилятору придётся так делать, да.
Другой вопрос — доступ к памяти, load, store, вот это всё
Компилятор имеет право его элиминировать
Например, локальную переменную можно выкинуть, если это не нарушит as-if rule
Инструкции можно переставить — можно ли их переставлять через односторонний барьер?
 
@VladD Гарантия заключается в том, что у .NET есть своя модель памяти (даже если ее нам не говорят). Именно у самой CLR. И барьеры ставятся именно в терминах этой модели памяти.
 
@PavelMayorov Вот, это уже конструктивнее
Проблема в том, что я не нашёл её в спеке
А статьи на MSDN или каком-нибудь Хабре могут устаревать, да и могут описывать реальность лишь с т. зр. Microsoft CLR, а не стандарта языка
 
"Выкинуть локальную переменную" - неправильное выражение. JIT не может выкинуть переменную, потому что переменная у него во входных данных, а не в выходных. Все что JIT может - это не выделять под переменную места на стеке.
Но запись в локальную переменную все равно будет (local) memory write с точки зрения модели памяти.
 
То есть JIT не имеет права сделать так: godbolt.org/g/Eg6CZx ?
Там переменная count просто алгоритмически элиминирована
 
6:18 PM
@VladD ...почему godbolt.org редиректит на goo.gl?!
 
@PavelMayorov Хм. Наверное потому, что у него сервис сокращений через goo.gl?
Сейчас сделаю полную ссылку
Чёрт, не влазит в сообщение
Ну или просто возьмите вот этот текст:
int test(int num)
{
    int count = 0;
    while (num)
    {
        count++;
        num &= (num-1);
    }
    return count;
}
И установите компилятор x86-64 clang (trunk) и ключи -O3 -march=haswell
Получается такой машкод:
test(int): # @test(int)
  popcnt eax, edi
  ret
(отойду на полчаса)
 
@VladD тут нет ни одного барьера, значит у JIT развязаны руки и он может не выделять память под count
 
6:55 PM
@PavelMayorov Угу, это понятно. Но непонятно, какие есть гарантии.
Например, что обязано сохраняться, а что может быть выкинуто.
Допустим, в присутствии барьеров и тому подобной синхронизации есть ограничения на кодогенерацию, и она должна быть более похожей на построчную.
А что с данными?
То есть для локальной переменной на C# гарантий нет, что она будет присутствовать в машинном коде. А где гарантии, которые даёт барьер? Заставляет ли присутствие барьера материализоваться локальные переменные (и какие из них?)
Ну и да, я имею в виду рассмотрение с точки зрения языка C#, ведь код я пишу не под конкретный jitter или конкретную CLR (или хуже того конкретный процессор).
 
7:36 PM
@VladD с точки зрения языка нет никакой материализации переменных
 
@PavelMayorov Но она есть с точки зрения барьера, ведь так?
Ну то есть барьер не пропускает записи в физические переменные области памяти
А присвоение переменным C# вовсе не означает записи в физическую область памяти
(Окей, не физическую, но давайте абстрагируемся от виртуальной памяти.)
@PavelMayorov В документации к барьеру упомянуты именно «физические» штуки: инструкции процессора и доступ к памяти. А вот документации на то, какие есть гарантии по командам C# и доступу к переменным, я не вижу. И соответствие между ними не документировано. (Ну то есть я не нашёл.)
Мне кажется, гарантии на барьер правильно давать в терминах модели памяти языка.
Но и её я не нашёл (официальной).
 
8:47 PM
@VladD ваши сомнения понятны. барьер служит указанием для процессора чтобы она не переставлял инструкции чтения записи (побочный эффект сброс буфера). То есть барьер - указание процессору, а вы спрашиваете про джит. Ну джит разумеется вставит транслирует этот барьер - раз. А атк как он не знает почему вставлен этот барьер, то, чтобы не накосячить, он будет НЕ оптимизировать вещи оптимизация которых нарушает барьер. Вряд ли это где то есть как спека, но в другом случае джит будет косячить
и кому нужен будет такой джит. А писать отдельный вариант джитирования для фреймворка вообще лишняя работа
 
9:15 PM
@vitidev Ну, э, проблема в том, что я вот не знаю, какие гарантии даёт джит. Но мне это и неинтересно, потому что джит может и вовсе отсутствовать
Я пишу на языке C#
И гарантии должны быть в терминах языка
> А писать отдельный вариант джитирования для фреймворка вообще лишняя работа
Если вы тянете в сторону «подсмотреть, что делали в фреймворке, и сделать так же» , то эта позиция у меня никогда не найдёт симпатии
 
@VladD а если отсуствует то воообще нет проблемы ибо эти инструкции обязаны попасть к процессору.
@VladD я тяну в сторону что барьер это базовый механизм. уберете барьер - нечем будет его заменить.
 
@vitidev Должны. Но могут попасть и без джита. Например, AOT.
@vitidev Вы говорите о каком барьере? О C#-овом или об инструкции процессора?
 
@VladD сишарповый барьер транслируется в инстркукцию
 
@vitidev (1) И только? (2) И где она расположена?
(3) А где гарантия этого?
Мы уже выясняли, что C# не обязательно транслирует построчно
Поэтому вопрос остаётся. Ну вы поместили где-то барьер в машинный код. Что он гарантирует с точки зрения C#?
Отсутствие перестановки записей в память — хорошо. А какое соответствие между записями в память и инструкциями C#?
Предположение о том, что присвоение однозначно кодируется записью в память, мы уже опровергли
 
1 ну еще служит сигналом комплиятору и джиту не особо оптимизировать чтобы не наделать глупостей. поэтому в этом месте оптимизации проще (слова липерта)
2 ее видно в дизасемеблере. в х86-64 это lockor или как оно там, а в арм свой вариант
3 ну ее для этого и придумали соственно. она даже в вашем любимом lock используетя
4 есть операции load и store. лоад - загрузка из памяти/кеша, сторе - сохранение в онные. вот мжеду ними барьер. Чтение из переменной - лоад, сохранение в переменную - сторе
 
9:30 PM
1. Слова Липперта отражают реальность существующей на тот момент имплементации CLR и не дают гарантий.
2. Видно, да. А где она расположена по отношению к другим инструкциям?
3. Я говорю о спеке, а не об одной конкретной имплементации. В спеке это есть?
4. Мы ведь уже выяснили, что присвоение переменной на C# не обязательно транслируется в store.
 
1 верно. но здравый смысл говорит что иного и быть не может.
2 в асме что ли? просто инструкция.
3 не знаю. спека это вообще сильно кратенько. могу сказать что в процессорах есть такая инструкция и в дотнете с самой первой версии есть эти барьеры и ничего не поменялось и даже не планируется
4 вспоминайте пример с event. вставьте мысленно барьер. Вот если джит докажет что НИКТО ен поменяет поле класса, то он может смело выкидывать локальную переменную. Но он не докажет это, а барьер видит и посокльку барьер и введен как возможность программисту вручную указать многопоточные места то "оптимиз
 
@vitidev 1. Здравый смысл не является источником информации, а лишь источником заблуждений. Например, популярное заблуждение насчёт C++ состоит в том, что будто бы «компилятор компилирует сложение целых чисел инструкцией процессора ADD, потому что как же иначе, поэтому целочисленное переполнение на Intel'овской платформе не ведёт к UB».
@vitidev 2. Если это просто инструкция непонятно где, то и гарантий она не даёт никаких. Например, она может быть в начале программы.
@vitidev 3. А если в спеке этого нет, то и гарантий этого тоже нет.
@vitidev 4. У нас было миллион примеров с ивентом. Какой именно из них вы имеете в виду? Приведите, пожалуйста, код, чтобы мы говорили об одном и том же.
4. Ну и рассуждения «джит делает так, потому что кто-то из нас считает, что по-другому нельзя», не выдерживают никакой критики
 
9:45 PM
здравый смысл говорит что эту инструкцию в процессоры и ввели чтобы дать инструмент программисту. Если ее выбросить из процессоров - то нужно чтобы чем то заменять. убрать ее - как убрать винт у вертолета и удивляться что в мире ничего не летает
2 язык первичен, джит вторичен. обязанность джита прекомпилировать но не во вред. барьеры штука древняя и нисколько не дотнетовская фича. Потому джит 10000% пишется с оглядкой на них.
3 не может. как и не может быть гарантии что не захотят отпилить винты от веротлетов. но после отпиливания как думете сколько народ будет летать и кому нужны будут так
 
@vitidev 1. Здравый смысл не является аргументом. Я приводил много контрпримеров, я сдаюсь.
Например, инструкция AAD в процессорах никому не нужна. Но она есть.
2. Единственным аргументом является спека и документация. То, что какая-то реализация C# как-то делала когда-то, аргументом для меня не является. Я пишу на языке C#, и гарантии мне может дать только его спека.
 
1 ну одно дело добавлять инструкции расширенные для особых случаев
другое дело выбрасывать базовые незаменимые

ну дока мсдн для барьера есть
 
@vitidev Да. Но она, как мы уже выяснили, ничего не гарантирует.
ещё раз давайте смотреть
 
@VladD она может быть ошибочна в выражениях но проблем с гарантией я не вижу. только ваши "а вдруг будет не так, вдруг джит будет плевать на все"
 
начальное значение переменных 0. Код: a = 1; thread.memorybarrier(); b = 1;. Опишите почему гарантировано, что в другом потоке не прочитается a = 0, b = 1
@vitidev Плевать на что? На ваши предположения о том, как он должен компилировать?
 
9:59 PM
уфф
1 не понял примера. обычные примеры - попарно переставленные переменные. у вас что то непонятое
2 читаем про барьер
Synchronizes memory access as follows: The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.

то есть он гарантирует не перестановку чтений/записи. А значит джит ОБЯЗАН это гарантировать.

возьмем евент
void Raise(){
var local=_fieldEvent;
 
Я понимаю, почему есть гарантия в коде store a, 1; memopybarrier; store b, 1 (условно). Но я не понимаю, почему вдруг код a = 1; thread.memorybarrier(); b = 1; обязан транслироваться в store a, 1; memopybarrier; store b, 1. (Аргумент «а как ещё может быть» не подходит)
 
@VladD потму что иначе барьер не будет выполняться. компилятор и джит не должны портить программу.
 
@vitidev 1. Ну это определение барьера по сути, разве нет?
 
1 пример вообще неправильный. нет там никаких гарантий ибо барьер там вообще не причем
 
@vitidev Что значит «не будет выполняться»? Дока не даёт этих гарантий
@vitidev Какой именно? Пожалуйста, всегда указывайте код, у нас много примеров
 
10:01 PM
@VladD дока дает гарантии непреодоления барьера туда сюда. выбросив локальную переменную джит преодолевает барьер
вот этот "Но я не понимаю, почему вдруг код a = 1; thread.memorybarrier(); b = 1;" не в тему вообще
 
@vitidev Дока даёт гарантии для нативного кода. Откуда вдруг взялись гарантии для кода на C#?
 
https://msdn.microsoft.com/ru-ru/library/system.threading.thread.memorybarrier%28v=vs.110%29.aspx
не вижу там слова нативный
 
Дока не даёт гарантий, что a = 1 превратится джиттером в store
@vitidev Там написано memory accesses
memory access в языке C# не бывает
и процессоров тоже не бывает
> The processor executing the current thread cannot reorder instructions
В терминах C# нет процессоров
поэтому эти гарантии — для машинного кода
 
с точки зрения шарпа джита вообще не существует. шарп дает инструкцию которую компилятор обязан скомпилировать правильно чтобы не поломать код. джит, в свою очередь, тоже обязан оптимизировать не ломая. Не шарп писали с оглядкой на джит, а джит пишется с оглядкой на шарп, поймите вы наконец,

так что в терминах шарпа чтение и запись - ЕСТЬ
а то что их джит может убрать - это уже его личная затея. но поскольку джит вторичен то обязан делать это осторожно чтобы не поломать код
 
а как C#-код мапится на машинный, не специфицировано
@vitidev в терминах C# чтение и запись переменных есть. но они вовсе не обязаны транслироваться в инструкции доступа к памяти (load/store)
 
10:07 PM
@VladD компилятор в компиляции в байткод барьер не сломает. джит обязан не поломать тоже иначе такой джит не будет иметь права на жизнь вовсе. посклько джит это пристройка ко всему для ускорения выполнения а не базовая часть
 
вы понимаете, что документация на memory barrier даёт гарантии в терминах команд процессора?
@vitidev Что означает «сломает»?
Сломает — это если что-то будет выполняться не по доке
А дока гарантий на команды C# не даёт
Сорри, вынужден убегать
Спокойной ночи!
 
ну а в чем еще давать. есть шарп. есть компилятор. даже если компилятор компилит построчно то все равно при выполнении процессор может переставить даже если джита вообще не существует в природе.

потому и термин такой. ведь компилятор не переставляет, а джит можно не учиывать - он пристройка. вот против кого направлено - в терминах того и пишут

а джит долежн НЕ МЕШАТЬ этому
иначе это не джит авредитель
 
@vitidev Компилятор не компилирует построчно. Гарантии должны быть в терминах языка, конечно. потому что соответствие между командами C# и нативными инструкциями не специфицировано
 
@VladD да. например пробьет барьер переставив операции
 
И да, я же предоставлял пример, что оптимизация не сводится к одной лишь перестановке
 
10:10 PM
я говорю про байткод. до нативных еще далеко
 
@vitidev Не было гарантий, что команды на C# будут в фиксированном порядке относительно барьера.
Почитайте ещё раз MSDN
Там гарантия только на итоговый нативный код
А его порядок по сравнению с кодом на C# может быть другим
 
вобще то имено так там и написано
что инструкции до барьера не будут перенесены за барьер
 
@vitidev Нет. Там написано про машинные инструкции
 
там про мемори доступ. а это чтение/запись
а не про переменные
 
@vitidev Чтение/запись переменных не обязательно отображается на доступ к памяти.
Я уже повторял это раз двести
Поэтому гарантии на чтение памяти не перекладываются на чтение/запись переменных
Сорри, должен убегать. Спокойной ночи!
 
10:14 PM
@VladD верно. но в вышепреведенном примере про евент оптимизация с выкидыванем локальной переменной приводит к перемещению доступа к памяти с ДО барьера в ЗА барьер, что нарушает
а потому джит не может выбросить локальную переменную. он без нее просто не сможет выполнить требование "не пересекать операциями чтения/записи барьер". Он может ввести хоть 100 новых переменных но выбростиь не сможет без нарушения. А значит локальная переменная выживет
даже не в виде переменной но это чтенизе запись будет до барьера, а после барьера будет читаться по новому адресу этой "переменной"
 

« first day (986 days earlier)      last day (2045 days later) »