Pull to refresh
20
0
Send message

Значение переменной в случае замыкания не просто "будет копироваться в поле экземпляра класса". Оно будет в нем храниться, потому что если вы из замыкания поменяете значение - оно поменяется и в самой переменной.

Локальные переменные reference type тоже хранятся в стеке. Простейший пример:

void SomeMethod()
{
  string some = null; // <--- локальная переменная, reference type
  //...
}

Вы же не станете утверждать, что этот null хранится в куче? :) Если сомневаетесь - проверьте тем же ildasm

C#

string some = null;
int someInt = 42;

IL
.method public hidebysig 
    instance void SomeMethod () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 7 (0x7)
    .maxstack 1
    .locals init (
        [0] string some,
        [1] int32 someInt
    )

    IL_0000: nop
    IL_0001: ldnull
    IL_0002: stloc.0
    IL_0003: ldc.i4.s 42
    IL_0005: stloc.1
    IL_0006: ret
} // end of method C::SomeMethod

IMHO, очевидно - две локальных переменных, одна value type, вторая reference type - хранятся абсолютно одинаково (в local variable list, а не в стеке). А через стек - только значения в них закидываются.

Можно, конечно, утверждать, что после компиляции jit-ом, значения value type будут хранится в стеке (в чем-то, на что указывает ESP) - но и это не будет соответствовать реальности, т.к. для небольших методов jit запихнет значения в регистры и обойдется совсем без стека (опять же, одинаково и для value type, и для reference type).

Стек - это детали реализации. На уровне C# стека нет (а StackOverflow есть :), на уровне IL стек есть, но переменные лежат не в нем, а в locals, а после JIT они могут лежать в стеке, а могут и не лежать. Причем как value types, так и значения ссылок reference types.

Вопрос, на который дан кривой ответ в статье - это не "в чем особенности реализации", а "Значимые и ссылочные типы — в чём отличия". Основное отличие, вот, по документации:

Variables of reference types store references to their data (objects), while variables of value types directly contain their data.

И то и то переменные, и те и те могут быть локальными (или не-локальными, полями, например), и те и те могут хранится в стеке. Переменные reference types хранят ссылки на данные (объекты), переменные value type хранят непосредственно данные. А про стек - это миф и копипаста.

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

Полностью согласен :)

Что плохого в том, что я обратил на это внимание?

Плохого - ничего. Проблемного - у новичков проблема с пониманием разницы между распараллеливанием и асинхроностью. Чтобы ее побороть - им пытаются объяснить что это две (почти) ортогональные вещи, что async/await не запускает потоки (сам по себе), и что это все про экономию, а не про "обработку в фоне".

А статья в стиле "вас обманывают, смотрите, там запускаются потоки!" исправлять эту проблему не помогает. Вот что у новичка, не понимающего как работает scheduler и task.yield отложится в голове? "видел статью на хабре, там на примере в 10 строк написано, что async/await на самом деле запускает фоновый поток и в нем все крутит". Вы же не раскрыли почему поток запускается, и как этого избежать, не расписали что "это потому что не pure, не делайте так, дети". Сделали небольшой трюк в коде, который джун не заметит и не поймет - и натянули на результат сенсационные опровержения "вам врут". Пользы от этого - никакой, и немного вреда. А не-новички и так понимают механизм.

Смысл - если ваша цель - экономия потоков, то правильным использованием будет  pure async / await. Потому что при неправильном использовании экономия потоков исчезает.

Но вообще я о том, что вы сами придумали утверждение, которое автор оригинальной статьи не делал, и сами же его опровергли:

асинхронная операция НИКОГДА не создает потока и в принципе не может его создать, но это не правда

vs

 If the async operation is pure, then there is no thread

Есть очень много утверждений, которые станут ложными при замене If [condition] -> НИКОГДА :)

Утверждение в древней статье: If the async operation is pure, then there is no thread.

Вы: я написал async await - и получил дополнительный поток.

Возможные варианты:

  1. Автор статьи всех обманывает уже 10 лет (ваш вывод)

  2. Ваш пример - это не pure async operation в том смысле, который вкладывал в него автор статьи.

async / await скопировали себе многие языки. Включая javascript, в котором поток всего один. Сама идея async / await - синтаксически удобный способ избегать блокировки потока при IO-bound вызовах. Понятно, что можно держать его неправильно и вручную явно/неявно запустить другой поток. И что там внутри в реализации на самом деле I/O completion threads используются даже при pure операциях. Не используйте async/await неправильно, всего делов :)

Значимые типы (value type) хранятся в стеке

ага, конечно...

class SomeClass
{
  int someField; // <--- int значимый? someField хранится в стеке?
}

и да, "локальные переменные value type хранятся в стеке" - тоже неправильный ответ (контрпример - замыкание).

---

неуправляемые ресурсы памяти

вместо того, что б создавать пользовательские финализаторы

не "памяти", и не "вместо". и собеседующий будет рад услышать про Safe handles.

А как Вы запишите незнакомое вам слово по-русски если не знаете что это вообще?
Вот стоит перед Вами ЧТО-ТО, что вы видите первый раз в жизни и не знаете как оно называется. Как Вы его назовете или запишите?

Что-то - это не слово. Слово - это единица речи.

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

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

Если же я попробую использовать "не завязанные на произношение" иероглифы, то 电池 другой носитель без знания китайского произношения прочитать не сможет. Потому что это не "молния + пруд" а "молния + что-то про воду, что на китайском звучит похоже на 也".

Невозможно передать иероглифами смысл слова "батарейка" другому носителю языка, если хотя бы один из нас не знает древнекитайского произношения слов "пруд" и "если". Даже если и я и другой носитель знают что такое 电,  氵и 也. Максимум, что можно передать - "электричество, что-то связанное с водой". Причем способа выяснить, что именно связанное с водой, не существует. Может пруд, а может голову кто-то моет.

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

Я не утверждаю, что иероглифы плохие (хорошие и интересные). Просто утверждение, что они не завязаны на произношение, и что их можно использовать в качестве некой "универсальной письменности", очевидно, не соответствует действительности. Как-то работает - "как-то", за счет огромной инерции, зубрежки (японцы), и хоть какого-то сходства диалектов и количества людей (китайцы).

Ок, уточню вопрос - как такое решать при записи другого диалекта или другого языка, на котором 丁 и 灯 - совершенно разные по произношению слова?

Я более чем уверен что на русском 丁 и 灯 достаточно сильно отличаются по произношению.

Мой пойнт - если фонетический компонент необходим для понимания неизвестных иероглифов - то иероглифы сильно завязаны на произношение. Что делает идею использовать их "в качестве письменности для другого диалекта или языка" нереализуемой, сразу по двум причинам.

  • Нельзя прочитать неизвестный иероглиф, т.к. фонетический компонент в другом языке не работает. Нельзя прочитать 蚞, 沐, 灯, 咖啡, если не знаешь китайского произношения. "что-то про животное, воду, огонь и рот" - вот максимум понимания.

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

Т.е. да, можно использовать иероглифы для записи любого языка. Если сначала выучить китайский :)

Но если для понимания иероглифа нужно знать его произношение, или, что хуже, его произношение в прошлом - то утверждение

иероглифы не завязаны на произношение и в принципе могут быть использованы в качестве письменности для другого диалекта или языка

не соответствует действительности. А "невозможность произнести незнакомый иероглиф" превращается в "Невозможность понять незнакомый иероглиф".

Ок, для китайца чтение незнакомых иероглифов идет по пути "слово связанное с огнем, которое звучит как 丁 - скорее всего лампа". Понимание иероглифа полностью завязано на произношение. Как такое решать при записи другого диалекта или другого языка, на котором 丁 и 灯 - совершенно разные слова? Часто ли встречаются иероглифы, произношение которых поменялось со временем, и для которых у современных китайцев чтение через произношение не срабатывает? Мешает ли это при изучении языка? :)

Есть ли способ прочитать 蚞, 沐 или 灯 не зная китайского произношения, кроме как выучить значения всех комбинаций?

Если иероглифы не завязаны на произношение, то почему 沐 - это "mù, мыть голову", а 木 - это "mù, дерево"? "Слово mù, связанное с водой 氵, которое звучит так же, как дерево 木" - поэтому записывается как "вода-дерево".

А 蚞 - это тоже mù - устрица, животное, которое звучит как mù, дерево, 木.

Может ли читатель, не знающий китайского произношения, но знающий 木,虫 и 氵, прочитать 沐 как "мыть голову" а 蚞 как "устрица"? Если да - то как?

В trunk-based есть бранчи, со своим workflow, просто они short living и они не используются в качестве основного способа работы над фичами (понятно что есть исключения, но если что-то можно сделать от мастера - то это делается от мастера). Это стори-бранчи от мастера. Основной юнит кодинга/интеграции/тестирования это бранч/стори, а не фича целиком.

Пишем на asp.net core / C#, Linux + легаси часть на asp.net / Windows. Чтобы было дешево - нужны хорошо разделяемые ресурсы (k8s) и container-friendly framework (== возможность запустить приложение как консольку, без обвеса в виде IIS/Tomcat/Application Server, )

Да, стоимость надо считать заранее. Гиг памяти сейчас около 5$ в месяц, если брать на Azure по полной цене, 2$ по предзаказу. Футпринт фреймворка примерно 150Mb на инстанс.

Статью хочу, но нужно время на написание, а его нет :)

А в чем конкретно проблема с организацией среды? Зависит от окружения, конечно, но мы, например, используем на trunk-based с небольшими app-specific костылями:

  • Приложение с multi-tenancy, 30+ мелких сервисов, k8s (Azure, AKS, мелковато нарезано).

  • У всех, и разработчиков, и QA, есть свой namespace, по умолчанию пустой. У каждого свой tenant (условно, внешний url vasya.dev.company.com или dev.company.com/vasya).

  • Есть общий нейспейс dev, куда настроен автодеплой по мержу в мастер (он же настроен и для production)

  • На дев кластере есть сервер-роутер, который ловит и входящие и кросс-сервисные запросы, и роутит их или по tenantid в нейсмпейс разработчика, если там нужный сервис есть. Или в общий dev, если в неймспейсе разработчика нужного сервиса нет.

  • QA в свои неймспейсы льют merge-ревизии c github (т.е. то, что будет в мастере после мержа) и тестируют по схеме "все как на проде + один измененный сервис"

  • Девелоперы - точно так же, но с возможностью отдебагать залитый сервис через bridge to kubernetes (telepresence, etc.)

  • по мержу все это улетает в мастер, и автодеплоем в dev и prod. Стейджинга нет (зачем? тестировать еще раз уже протестированное?).

  • для фронта та же схема, но с заливкой tenant-specific статики вместо бэка.

  • ну и да, все изменения под feature flags, потому что деплой фич на прод != доступность фич реальным пользователям. После деплоя делаются туры, какие-то тенанты получают фичи раньше/позже, feature flag management - это отдельная ниша, под нее есть всякие devcycle.com и launchdarkly.com. И это не бэкэнд стори.

  • Чтобы это работало нужны unit tests, code review до отдачи в тест и возможность задеплоить сервис куда угодно в один клик. Ну еще мониторинг и вера в команду :)

Цена вопроса - до гига памяти в общем кластере на девелопера/QA (на дев окружении реквесты/лимиты меньше можно выставить).

Есть еще более агрессивные модели - тот же github flow, где деплой в прод делается из PR до мержа, и мерж проходит только если прод не упал. Но это мерж-экстремизм :)

Но что если мы не готовы так радикально перестраиваться? Что если у нас не всё хорошо с тестами? Что если реальность требует где-то вне продакшена проверять изменения?

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

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

На скрине в отчете: малварь поставился в c:\Windows\Microsoft.NET\Framework\v4.0.30319\

Киберисследователи: сотрудник пытался загрузить пиратскую версию Microsoft .NET Framework!

модераторы смогут отстоять свою позицию, хотя бы в части отношения к ИИ-контенту.

Они в прошлый раз не смогли право не использовать кастомные местоимения отстоять (все спустили на тормозах). А тут - попытки зарубить основные KPI и путь монетизации. Без шансов, кожаные мешки! Как бывший мод, вангую - CM-ы буду просто сидеть и делать вид что все отлично. Может еще в блог пост напишут как все хорошо. Через месяц-два наберут новых модераторов и все будет как раньше.

Это LINQ, там под капотом всех методов одна и та же реализация - вернуть новое дерево выражений с довешенным сверху method call. Реализацией и разбором что делать с каждым вызовом занимается конкретный LINQ Provider. Существующие провайдеры при виде method call с тем с именем метода OrderBy, но без аргумента будут падать.

Они, в принципе, и при виде просто нового Order будут падать, но, по крайней мере, с конкретной ошибкой что метод не поддерживается, а не с NRE. Так что это все ради обратной совместимости.

Скорее всего это про READ_COMMITTED_SNAPSHOT - с ним читается копия c одним локом SCH-S, без него - ставятся page / row S-локи, блокирующие изменения.

Любоваться распечаткой base64 вполне можно - https://mobile.twitter.com/base64art

1
23 ...

Information

Rating
4,339-th
Location
Беларусь
Date of birth
Registered
Activity