Однозначно, работать есть над чем. Не могу с уверенностью говорить, не зная всей вашей кухни, но я думаю, стоит существенно увеличить путь от репозитория до рабочего окружения, чтобы неаккуратный мерж (в ночь, что частично объясняет) не приводил к такому факапу. Может быть короткий путь и удобен, но иногда есть смысл создавать неудобства искусственно.
Возможно, стоит подкорректировать процесс деплоя так, чтобы новые версии применялись не ко всем пользователям сразу, а постепенно с чётко заданными долями и интервалами. Тогда, если факап случится, можно будет пресечь его пока масштабы трагедии невелики. У вас такое применяется для крупных обновлений. Это хорошая практика. Полагаю, стоит развить этот опыт.
Конечно же, всё это имхо и, возможно, всё это у вас и так есть, просто что-то прямо вообще невероятное случилось.
Я подумал об этом, но только после отправки комментария.
Замечу, что у такого решения есть недостаток — вычислительная сложность у него O(n*m) где n — суммарное количество элементов в подмассивах, m — количество подмассивов. У concat это O(n).
Хороший подход к написанию статьи. Прямо жизнь программиста в миниатюре — кодинг параллельно личной жизни. Но меня эта история тронула ещё и тем, что в ней я заметил несколько пересечения со своей. Я тоже встречался с девушкой по имени Катя. Длилось это 4.5 года. Когда у нас только начался разлад в середине этого срока, в попытках хоть как-то отвлечься, я начал писать свой js движок. После расставания в апреле 2015-го я так же подумал, что у меня теперь много свободного времени и почти полностью переработал его. Только помимо этого я ещё сменил город и место работы, почти как DrPass
Во-первых, Вы засоряете память сборками. От такого решения пропадает основной плюс скриптовых языков — подгрузил, выполнил, забыл. С тем же успехом можно и C# компилировать.
Во-вторых, Вы описали как достоинство возможность использовать типы из пространства имен System. Хоть pure-dotnet движков JavaScript и немного (а живых и того меньше), но каждый из них так умеет. И они не имеют описанной выше проблемы с памятью.
Для меня самое удивительное во всех таких «исследованиях» есть само наличие такой пары «связанных» факторов. Такое чувство, что они написали разные слова на поле для дартса и теперь куда попадут, то и связывают.
--скептик-mode-on
Представим ситуацию: я получил физический доступ к компьютеру (с достаточно мощным процессором и контроллером памяти, чтобы успеть 540 000 раз дёрнуть память за 64 миллисекунды), но у меня там юзерская учётка, а я хочу админку. Я знаю, что где-то в памяти лежит маска моих прав, но доступа у меня туда нет (Protected-mode, все дела), поэтому я долблюсь в «физически» соседнюю память, чтобы как-то повлиять на ту, где лежит маска.
Сопутствующие вопросы:
1) Куда долбиться? Где та самая соседняя строка памяти в терминах указателей?
2) Что делать со страничной организацией памяти? Из-за неё те циферки, что записаны в каком-нибудь void* ни разу не соответствуют тем, что на самом деле.
3) Предположим, я решил два предыдущих вопроса, начал долбить и тут бац — процессор переключается на другой процесс. Я этого не замечу, если не переопределю вектор прерывания (чего я сделать не смогу, иначе самой задачи бы не было). Значит долбить я буду дольше.
4) Физическая память закончилась, страница, в которую я долблю, упала в swap, потом вернулась. Куда? Куда сейчас долбить? Как это заметить?
5) И напоследок: в защищённом режиме (а иные сейчас нет смысла рассматривать) процессор просто не отправляет команды контроллеру памяти, если нет прав на доступ к участку памяти.
--скептик-mode-off
Раскрутка, если мне не изменяет память, это несколько другое.
Сначала на каком-то существующем языке пишется полное по-Тьюрингу подмножество языка (к примеру, один условный оператор и один цикл), после этого на уже новом языке переписывают этот компилятор и продолжают разработку нового языка на новом языке. Такой подход ускоряет разработку, если новый язык, в сравнении со старым, к этому способствует. Так был написан Pascal, к примеру.
Тут же всё несколько иначе — версия языка уже перемахнула за 1.0, а он всё ещё содержал «чужой» код. Это именно переписывание.
Когда я вышел из статуса RO, гиктам уже отделился, поэтому там мой статус не поменялся. Сейчас новым захабренным будут менять статус на всех трех проектах. То есть тем, кому повезло получить инвайт за три прошедших месяца, придется пробиваться на гитайм в общем порядке через песочницу или, таки, что-то будет предпринято?
Одна деталь: не факт, что указатель всё время будет валидный. Объекты ведь могут перемещаться по памяти. И они будут перемещаться.
Тут стоит попробовать передать GCHandle этого объекта, но я не уверен, что среда не схватит за руку при попытке использовать. И даст ли она вообще использовать или отругается на то, что в использующем домене нет объекта с таким handle'ом.
Оптимизацией занимается и компилятор, и JIT. Иначе не было бы разницы между Release и Debug. Раскручивание циклов, удаление мертвого кода, удаление неиспользуемых переменных и еще много чего выполняется именно на этапе трансляции из C# в IL
Обычно для вызова методов используется callvirt. Где-то читал, что они этим сэкономили на явной проверке валидности указателя, так как callvirt проверяет и босает NullReference если надо
Возможно, стоит подкорректировать процесс деплоя так, чтобы новые версии применялись не ко всем пользователям сразу, а постепенно с чётко заданными долями и интервалами. Тогда, если факап случится, можно будет пресечь его пока масштабы трагедии невелики. У вас такое применяется для крупных обновлений. Это хорошая практика. Полагаю, стоит развить этот опыт.
Конечно же, всё это имхо и, возможно, всё это у вас и так есть, просто что-то прямо вообще невероятное случилось.
Замечу, что у такого решения есть недостаток — вычислительная сложность у него O(n*m) где n — суммарное количество элементов в подмассивах, m — количество подмассивов. У concat это O(n).
и не такой красивый
Во-вторых, Вы описали как достоинство возможность использовать типы из пространства имен System. Хоть pure-dotnet движков JavaScript и немного (а живых и того меньше), но каждый из них так умеет. И они не имеют описанной выше проблемы с памятью.
Посмотрите на Jint, к примеру
Представим ситуацию: я получил физический доступ к компьютеру (с достаточно мощным процессором и контроллером памяти, чтобы успеть 540 000 раз дёрнуть память за 64 миллисекунды), но у меня там юзерская учётка, а я хочу админку. Я знаю, что где-то в памяти лежит маска моих прав, но доступа у меня туда нет (Protected-mode, все дела), поэтому я долблюсь в «физически» соседнюю память, чтобы как-то повлиять на ту, где лежит маска.
Сопутствующие вопросы:
1) Куда долбиться? Где та самая соседняя строка памяти в терминах указателей?
2) Что делать со страничной организацией памяти? Из-за неё те циферки, что записаны в каком-нибудь void* ни разу не соответствуют тем, что на самом деле.
3) Предположим, я решил два предыдущих вопроса, начал долбить и тут бац — процессор переключается на другой процесс. Я этого не замечу, если не переопределю вектор прерывания (чего я сделать не смогу, иначе самой задачи бы не было). Значит долбить я буду дольше.
4) Физическая память закончилась, страница, в которую я долблю, упала в swap, потом вернулась. Куда? Куда сейчас долбить? Как это заметить?
5) И напоследок: в защищённом режиме (а иные сейчас нет смысла рассматривать) процессор просто не отправляет команды контроллеру памяти, если нет прав на доступ к участку памяти.
--скептик-mode-off
День — «он мой», мужской род.
Простите, не удержался
Они резиновые что-ли?
биомассы.Сначала на каком-то существующем языке пишется полное по-Тьюрингу подмножество языка (к примеру, один условный оператор и один цикл), после этого на уже новом языке переписывают этот компилятор и продолжают разработку нового языка на новом языке. Такой подход ускоряет разработку, если новый язык, в сравнении со старым, к этому способствует. Так был написан Pascal, к примеру.
Тут же всё несколько иначе — версия языка уже перемахнула за 1.0, а он всё ещё содержал «чужой» код. Это именно переписывание.
Тут стоит попробовать передать GCHandle этого объекта, но я не уверен, что среда не схватит за руку при попытке использовать. И даст ли она вообще использовать или отругается на то, что в использующем домене нет объекта с таким handle'ом.
Вот объяснение этой штуки: blogs.msdn.com/b/ericgu/archive/2008/07/02/why-does-c-always-use-callvirt.aspx