All streams
Search
Write a publication
Pull to refresh
222
0
Алексей @PsyHaSTe

Зигохистоморфирующий

Send message
Да, дал маху, если не возражаете, добавлю ваш совет.
Немного промахнулся, см. ниже )
Я правильно понимаю, что в данном случае нет ничего необычного — глядя в таблицу методов (с рутами), GC видит, что в дальнейшем на переменную никто не ссылается и просто принимает решение о том, что её можно удалить?

Никакой таблицы методов, насколько я помню механизм, у каждого объекта есть свойство, которое показывает строчку (вернее, адрес команды), после которой он может быть безопасно удален. Поэтому например метод GC.KeepAlive выглядит так:
[MethodImpl(MethodImplOptions.NoInlining), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), __DynamicallyInvokable]
public static void KeepAlive(object obj)
{
}

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

А в остальном да, все верно.

Не могли бы вы поподробнее описать, что здесь имелось в виду и как на самом деле на нижнем уровне происходит вызов (через call или callvirt, по какому адресу осуществляется вызов, какое значение имеет указатель this и как влияет на вызов удаление экземпляра сборщиком мусора).

когда вы пишете
void Foo(int a,int b)
{
   c = a+b;
}

компилятор превращает это в такой код:
static void Foo(object this, int a,int b)
{
   this.c = a+b;
}

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

что касается call и callvirt можно почитать об этом, например, здесь.
Спасибо, добавил.
Да, про CriticalFinalizerObject забыл, сейчас добавлю.

Нет, это не перепечатка, основная информация из Clr via C# и Pro .Net perfomance. Последняя мне очень понравилась, в еще намного легче читать, чем Рихтера. Хотя, конечно, классику знать надо.
Да, фейл. Прошу прощения *sorry*
Для начала нам понадобится бесконечный список:

Теперь можно написать:

И зачем? Поражают такие люди, особенно на всяких программерских форумах для новичков, когда велосипедят linq-код просто для того, чтобы показать, что они его знают. На обычных циклах даже текста меньше займет, не говоря про понятливость/производительность. А уж про подводные камни наподобие упаковки для значимых типов вообще не хочется вспоминать. Тогда уж:
IEnumerable<T> Infinite<T>() {while(true) yield return default(T);}

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

И да, речь действительно не об этом, поэтому я и на предыдущий комментарий не ответил. Засим завершим беседу.
Я не спорю, что человека, который не закрывает ресурсы юзингом, нужно гнать в шею. Но упомянуть про обязательное освобождение в деструкторе, как последнем рубеже обороны, в статье про IDisposable считаю необходимым.
Для всех стандартных классов, реализующих IDisposable, так лучше?
Это значимый тип данных. Значение переменной valType будет храниться в стэке.

Дальше можно не читать.

100 раз говорили: значимые типы почти всегда размещаются в куче, т.к. являются полями классов. А на стеке размещаются только локальные переменные значимого типа. А ссылочные типы далеко не всегда размещаются в куче, см. stackalloc. Поэтому это утверждение не просто ошибочное, а в корне неверное.

Эрик давно уже статью целую наваял: если бы это было так, были бы «стековые» и «кучевые» типы данных (stack and heap values), а не «значимые» и «ссылочные».

Советую ознакомиться:

blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
Dispose также вызывается в деструкторе, если какой-то умник забудет вызвать его «вручную».
Странно, что он так взъелся на JIT и GC. Тот же Рихтер имеет противоположенное мнение: что у JIT'а больше вариантов для оптимизаций, а GC зачастую эффективнее, чем ручное управление памятью, так как выделение является крайне дешевой операцией по сравнению с С/С++. Существует проблема фрагментации, с этим не спорю, но при грамотном построении приложения получается, что GC даже быстрее, как раз из-за описанных преимуществ. Не говоря о том, что на хабре полгода назад была статья, что будет новый JIT, кстати, вот она.

Хотя в целом С++ побыстрее, конечно, будет, да и грамотно работают с памятью далеко не все. Но это скорее не проблемы языка, а проблемы программистов, которым проще засунуть планку на 4гб, чем оптимизировать приложение. В целом по моим ощущениям C# медленнее С++ в среднем на величину около 30%, а иногда даже быстрее. Зато плюшек у него ощутимо больше. Хотя, конечно, могли бы JIT сделать поумнее: например, компилировать быстро без оптимизаций, а затем собирая статистику, перекомпилировать «hot path» в приложении. В конце концов, раз уж ругают «монструозный .Net», жрущий кучу ресурсов и памяти, пусть хоть с толком ими распоряжается.
Ничего страшного, видимо, привычка у меня пошла еще со времен учебников, где половина формул приводится со словами «очевидно» и «доказательство оставим для тренировки читателю».

Решение может приведу, ближе к выходным. Пока рабочая неделя, нет сил на детализированное доказательство, а концепцию я расписал выше.
При чем тут целочисленные ограничения? Еще раз:
1) СНИМАЕМ ограничение на целочисленность
2) Решаем любым способом на континууме возможных значений оптимальную точку, можно методами нелинейного программирования: Розенброк вполне подходит, если доп. ограничения какие-то — стандартно введем штрафную/барьерную функцию. Получим точку. Можем повторить несколько раз для различных точек, чтобы быть уверенными, что мы попали в глобальный экстремум.
3) Очевидно, что оптимальное целочисленное решение будет находится в окрестности нецелого решения. Т.О. расширяем область до тех пор, пока на окружности не будет лежать хотя бы одной точки с целочисленными координатами.
4) записываем ответ.

У меня был пример одной из лабораторок, где решалась эта задача, но к сожалению за давностью не смог найти.
Может я чего-то не понимаю, но по-моему эта задача похожим образом решается во всяких методичках, достаточно просто принять, что мы перевозим не товары, а партии, а затем снимая ограничение на целочисленность находим тем же МВГ допустимое решение, а потом ищем ближайшее к нему целочисленное.
Спасибо. Не могу лайкнуть, так что просто отпишусь так.
Ясно. То есть по вашей логике если физика, математика и пр вышли в далекие времена из философии, то они на нее опираются? И непонятно, зачем капающая лопата сдалась…

А ваше высказывание про «физическую логику» заставляет меня потерять всякий интерес к беседе, т.к. очевидно, что вы не разбираетесь в вопросе. Всего доброго.
Ну, в случае с IList, это не баг, это фича. Имеются соответствующие свойства, которые показывают, какой перед нами IList: read-only, fixed-size или variable-size.

угу, зачем нам вообще ООП, давайте везде пихать if else switch case. Смысл как раз и в том, чтобы приводить к нужному интерфейсу, а дальше с ним работать. Что мешает имплементировать нужные интерфейсы в любом количестве, как это сейчас и бывает?

У нас есть T[], т.е. массив, но он не интерфейс.

Не уловил смысла в этой фразе. T[] от int[] не отличается ничем, кроме того, что тип T нам пока неизвестен.

Думаю, причина примерно та же, почему мы не можем считать одинаковыми классы:

class Foo { public int _foo; }
class Bar { public int _bar; }

в этом есть определенный смысл, но от такого каста пользы было бы много.
Да там много чего интересного можно было бы сделать. Например
        private delegate void Del1();

        private delegate void Del2();
        static void Main()
        {
            Del1 del1 = () => Console.WriteLine("Foo");
            Del2 del2 = (Del1) del1;
        }


то есть считать делегаты с одной сигнатурой — алиасами одного и того же делегата. Но нет, это ведь так сложно…

Я уже молчу про IList. Как один умный человек, насколько лучше было бы изначально сделать такие интерфейсы:

  • Just Enumeration IEnumerable(T)
  • Readonly but no indexer (.Count, .Contains,...)
  • Resizable but no indexer, i.e. set like (Add, Remove,...) current ICollection(T)
  • Readonly with indexer (indexer, indexof,...)
  • Constant size with indexer (indexer with a setter)
  • Variable size with indexer (Insert,...) current IList(T)


а не наследовать массивы от IList(T), а потом бросать исключения при вызове половины методов…

Information

Rating
Does not participate
Registered
Activity