Здравствуйте, Маслаков Михаил, Вы писали:
ММ>Ёлки палки, я до самого низа докопал функционал доставания схемы. Повсюду кидал эксепшены, чтобы хоть какую-то дебаг информацию получать ММ>Выходило, что при компиляции таблицы в схеме были, но тем не менее в Error List ошибка оставалась. ММ>Так что ты прав, всё дело было в кеше интеллисенса. Есть какой-то способ его сбросить, не рестартуя студию?
Да, дело такое. Обидно, что даже рестарт студии не всегда спасает . Особенно ярко подобные артефакты вылазят при апгрейде немерла. Не постил этот баг т.к. сначала хотел понять его принцип, но так и не понял. Пока просто не доверяю ошибкам в error list, а вытаскиваю output и делаю ребилд.
Re[4]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, VladD2, Вы писали:
ММ>>Проблема судя по всему в Entity Framework, который я использую для доступа к данным (через отдельный class library проект). ММ>>Как только я добавляю код, в котором есть доступ к данным через ObjectQuery, компилятор вешается.
Я кажется понял, в чем дело.
— В режиме интеграции компилятор загружает типы сборки не сразу, а по мере необходимости.
— Тип ObjectQuery[T] унаследован от одноименного, но не генерик типа ObjectQuery. ( class ObjectQuery<T> : ObjectQuery {} )
— Компилятор, загружая тип ObjectQuery[T] пытается обойти всех его предков.
— К моменту обработки родительского типа (ObjectQuery) компилятор уже загрузил информацию о типе ObjectQuery[T].
— Компилятор пытается найти тип ObjectQuery среди уже загруженных типов.
— На беду, поиск типа производится без учета параметров, только по имени, от которого отбрасывается символ ` и все, что расположено за ним. Если тип с подходящим именем найден и он единственный, то они и считается подходящим. (Такая логика допустима только в том случае, если к этому моменту будут загружены все типы всех сборок, а в режиме интеграции это условие не соблюдается)
— Количество параметров проверяется при поиске только в том случае, если найдено несколько одноименных типов. Более строгая проверка параметров откладывается на поздний этап. В коде по этому поводу есть коммент "incorrect number of args is reported later in a cleaner way" — это строка 377 файла NamespaceTree.n Но дело до этого более позднего этапа увы не доходит.
— Таким образом, в качестве родительского типа для ObjectQuery[T] используется информация о нем же.
— Далее компилятор натыкается в коде на конструкцию ObjectQuery[T].Where() и пытается найти объявление метода Where сначала с классе ObjectQuery[T] (безуспешно), а затем в базовом классе. А поскольку базовым считается тот же ObjectQuery[T], то компилятор уходит в бесконечный цикл, который сваливается по OutOfMemory.
Вот основной виновник торжества:
\ncc\hierarchy\NamespaceTree.n (363)
public LookupType (split : list [string], args_count : int) : option [TypeInfo]
{
def search (cached) {
| (x : TypeInfo) :: xs =>
if (args_count == -1 || args_count == x.TyparmsCount)
Some (x)
else
search (xs)
| [] => None ()
}
match (TryPath (split)) { <------- Поиск без учета args_count
| TypeInfoCache.Cached (tc) =>
// incorrect number of args is reported later in a cleaner way
Some(tc); <------- откладываем проверку
| TypeInfoCache.NotLoaded (e) =>
e.ConstructTypeInfo (Path (split), true);
// incorrect number of args is reported later in a cleaner way
Some(e.tycon) <------- откладываем проверку
| TypeInfoCache.NotLoadedList as val =>
def cached = Path (split).LoadValue (val);
search (cached)
| CachedAmbiguous (all) => search (all)
| TypeInfoCache.MacroCall | TypeInfoCache.No
| TypeInfoCache.NamespaceReference => None ()
}
}
Фикс я в принципе уже написал, выложу как завершу тестирование.
Юнит тест похоже тут не написать, т.к. ошибка проявляется только в режиме интеграции.
Здравствуйте, VladD2, Вы писали:
VD>А вот это странно. Что в интеграции такого, что меняет поведение? Тут что-то не так.
В режиме интеграции типы из внешних сборок грузятся не все сразу, а по мере необходимости. В режиме интеграции все так и работает — я проверял под отладчиком, изначально ноды, соответствующие неймспесам пустые, и дополняются типами по ходу компиляции.
Обычную компиляцию не дебажил, прошелся по исходникам глазками — в ManagerClass.Run() вызывается LoadExternalLibraries() и дальше по цепочке, пока не вызовется LibraryReferenceManager.LoadTypesFrom(lib), в которой все типы и прогружаются.
Провел эксперимент: Взял приаттаченный проект, открыл исходник, раскомментировал строку и сразу загрузка проца и памяти поползли вверх, пока не случился OutOfMemory. Закрыл окно с исходником, и тут же в студии вызвал Rebuld All — все нормально скомпилировалось.
Здравствуйте, seregaa, Вы писали:
S>Здравствуйте, VladD2, Вы писали:
VD>>А вот это странно. Что в интеграции такого, что меняет поведение? Тут что-то не так.
S>В режиме интеграции типы из внешних сборок грузятся не все сразу, а по мере необходимости. S> В режиме интеграции все так и работает — я проверял под отладчиком, изначально ноды, соответствующие неймспесам пустые, и дополняются типами по ходу компиляции.
В режиме компиляции происходит тоже самое. В этом плане ничего не менялось. Разница только в том, что перезагрузку типов может происходить многократно (при изменении сборок, например).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, Маслаков Михаил, Вы писали:
ММ>Всем привет!
ММ>Решил написать Nemerle версию NerdDinner'а. В основном для себя, чтобы поближе с языком познакомиться. Если реализация будет близка к конечному результату, то можно будет и выложить для примера.
ММ>Так вот, столкнулся с проблемой — студия почему-то постоянно отжирает себе одно из 4х ядер процессора, как вовремя компиляции, так и вовремя разработки. Количество отъедаемой памяти при этом бытро растёт, пока компилятор не вываливается с OutOfMemoryException.
ММ>Что-либо делать в таких условиях реально сложно, тем более что языка то ещё толком не знаю. ММ>Может подскажите, куда копать?
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, catbert, Вы писали:
C>>Еще один похожий случай, на этот раз с SQLite.NET: http://code.google.com/p/nemerle/issues/detail?id=1275
VD>Эх. А как окружение воспроизвести?
Ну, там проект в комментариях прикреплен.
Re[8]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, VladD2, Вы писали:
S>>В режиме интеграции типы из внешних сборок грузятся не все сразу, а по мере необходимости. S>> В режиме интеграции все так и работает — я проверял под отладчиком, изначально ноды, соответствующие неймспесам пустые, и дополняются типами по ходу компиляции.
VD>В режиме компиляции происходит тоже самое. В этом плане ничего не менялось. Разница только в том, что перезагрузку типов может происходить многократно (при изменении сборок, например).
Прошелся по коду в отладке еще раз. На самом деле компилятор вылетает и в режиме интеграции и в режиме компиляции. А типы из внешних библиотек грузятся все сразу — в методе ManagerClass.LoadExternalLibraries(). Баг проявился из за того, что не все используемые библиотеки были прописаны в референсах проекта:
MvcApplication4 содержит ссылку на библиотеку NNerdDinner.Domain, классы которой унаследованы от классов Entity Framework-а (System.Data.Entity). При этом в проекте MvcApplication4 ссылка на Entity Framework отсутствует.
Компилятор C# в такой ситуации отказывается компилировать проект, требуя явно прописать ссылки на все библиотеки. А компилятор Nemerle пытается подгружать типы из неизвестных (не прописанных в reference-ах) библиотек на лету во время компиляции. И тут типы грузятся не все сразу, а только по мере необходимости. А как я уже писал выше, алгоритм поиска типов в сборках написан в предположении, что все типы сборки уже загружены, поэтому здесь поиск лажает и классу ObjectQuery<T> в качестве базового прописывается этот же ObjectQuery<T> (вместо ObjectQuery). Эта циклическая ссылка и вызывает переполнение памяти.
Есть два варианта исправления:
— аналогично компилятору c# отказываться компилировать проект с отсутствующими сылками
— исправить логику поиска типа в сборке. (это метод LookupType класса NamespaceTree). И возможно придется допиливать не только это метод. Код работы с типам вызывает ощущение того, что он писался в до-генериковую эпоху, и поддержка генериков была прикручена позже и как видно не совсем корректно.
Какой вариант выбираем?
p.s. минимальный солюшн, демонсирирующий баг, прикреплен к описанию дефект на гуглкоде http://code.google.com/p/nemerle/issues/detail?id=1230 . Солюшн самодостаточен, независим от Entity Framework или других внешних библиотек.
Здравствуйте, seregaa, Вы писали:
S>Есть два варианта исправления:
S>- аналогично компилятору c# отказываться компилировать проект с отсутствующими сылками
S>- исправить логику поиска типа в сборке. (это метод LookupType класса NamespaceTree). И возможно придется допиливать не только это метод. Код работы с типам вызывает ощущение того, что он писался в до-генериковую эпоху, и поддержка генериков была прикручена позже и как видно не совсем корректно.
S>Какой вариант выбираем?
Тот что проще в реализации, т.е. видимо первый.
S>p.s. минимальный солюшн, демонсирирующий баг, прикреплен к описанию дефект на гуглкоде http://code.google.com/p/nemerle/issues/detail?id=1230 . Солюшн самодостаточен, независим от Entity Framework или других внешних библиотек.
Может сам попробуешь исправить? Если не выйдет, я завтра постараюсь поправить (сегодня голова не варит).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, VladD2, Вы писали:
VD>Может сам попробуешь исправить? Если не выйдет, я завтра постараюсь поправить (сегодня голова не варит).
ok, попробую.
Здравствуйте, VladD2, Вы писали:
VD>Может сам попробуешь исправить? Если не выйдет, я завтра постараюсь поправить (сегодня голова не варит).
А как правильнее вывести сообщение об ошибке и прервать компиляцию? Util.ice выводит очень уж страшное сообщение с припиской "please report a bug to bugs.nemerle.org. You can try modifying program near this location.", что не очень то подходит в данном случае. А Message.Error() не прерывает компиляцию.
Здравствуйте, seregaa, Вы писали:
S>А как правильнее вывести сообщение об ошибке и прервать компиляцию? Util.ice выводит очень уж страшное сообщение с припиской "please report a bug to bugs.nemerle.org. You can try modifying program near this location.", что не очень то подходит в данном случае. А Message.Error() не прерывает компиляцию.
Может Message.FatalError?
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[11]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, seregaa, Вы писали:
S>Здравствуйте, VladD2, Вы писали:
VD>>Может сам попробуешь исправить? Если не выйдет, я завтра постараюсь поправить (сегодня голова не варит).
S>А как правильнее вывести сообщение об ошибке и прервать компиляцию? Util.ice выводит очень уж страшное сообщение с припиской "please report a bug to bugs.nemerle.org. You can try modifying program near this location.", что не очень то подходит в данном случае. А Message.Error() не прерывает компиляцию.
ice это если компилятор не может дальше работать и сам не понимает почему.
Message.FatalError(), емнип прерывает компиляцию.
Re[12]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, WolfHound, Вы писали:
S>>А как правильнее вывести сообщение об ошибке и прервать компиляцию? Util.ice выводит очень уж страшное сообщение с припиской "please report a bug to bugs.nemerle.org. You can try modifying program near this location.", что не очень то подходит в данном случае. А Message.Error() не прерывает компиляцию. WH>Может Message.FatalError?
Здравствуйте, Ziaw, Вы писали:
S>>А как правильнее вывести сообщение об ошибке и прервать компиляцию? Util.ice выводит очень уж страшное сообщение с припиской "please report a bug to bugs.nemerle.org. You can try modifying program near this location.", что не очень то подходит в данном случае. А Message.Error() не прерывает компиляцию.
Z>ice это если компилятор не может дальше работать и сам не понимает почему.
В моем случае причина ошибки известна, и это не внутренняя ошибка компилятора, а ошибка во внешнем файле проекта. Поэтому тут имхо ice
(internal compiler error) не очень подходит.
Z>Message.FatalError(), емнип прерывает компиляцию.
ага, точно!
Здравствуйте, VladD2, Вы писали:
S>>- аналогично компилятору c# отказываться компилировать проект с отсутствующими сылками
S>>- исправить логику поиска типа в сборке. (это метод LookupType класса NamespaceTree). И возможно придется допиливать не только это метод. Код работы с типам вызывает ощущение того, что он писался в до-генериковую эпоху, и поддержка генериков была прикручена позже и как видно не совсем корректно.
S>>Какой вариант выбираем?
У тебя получилось, что компилятор теперь орет не только на использование типа из сборки которая не подключена, а на то, что не подключены сборки на которые хоть как-то (даже опосредовано) ссылаются зависимые сборки. В результате компилятор орет на полную фигню. Даже если тип никогда и ни где не используется, компилятор требует явно подключить ВСЕ зависимые сборки.
Это просто ужасно! В солюшене из тройки проектов уже просто невозможно работать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, VladD2, Вы писали:
VD>У тебя получилось, что компилятор теперь орет не только на использование типа из сборки которая не подключена, а на то, что не подключены сборки на которые хоть как-то (даже опосредовано) ссылаются зависимые сборки. В результате компилятор орет на полную фигню. Даже если тип никогда и ни где не используется, компилятор требует явно подключить ВСЕ зависимые сборки.
VD>Это просто ужасно! В солюшене из тройки проектов уже просто невозможно работать.
Приведи плиз пример. Я проверил пару сценариев и пока компилятор работает аналогично компилятору шарпа.
К примеру, создаю прокта, содержащий ссылку на System.Data.SqlServerCe и не содержащий ссылку на System.Data. В проекте создаю код, испльзующий SqlCeEngine (уникальный для этой сборки класс, не унаследованный от классов внешних сборок), код успешно компилируется и шарпом и немерле. Затем добавляю в проект код, испльзующий SqlCeCommand (унаследованный от DbCommand из неподцепленной сборки System.Data) и оба копилятора начинают ругаться на отсутствие сборки.
Здравствуйте, seregaa, Вы писали:
S>Приведи плиз пример. Я проверил пару сценариев и пока компилятор работает аналогично компилятору шарпа.
Ситуация была такая.
Есть проект в котором делается реализация интерфейса. Сам интерфейс описан в другом проекте (но это видимо не важно).
Так вот при реализации интерфейса человек оставляет публичный метод который содержит параметр с типом из другой сборки.
Далее в другом проекте создается тип реализующий интерфейс и сразу же приводится к интервейсу. Но появляется это сообщение (плюс еще меседжбокс) и ничего не работает.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: Проблема с интеграцией, компилятор "ест" память
Здравствуйте, VladD2, Вы писали:
VD>Так вот при реализации интерфейса человек оставляет публичный метод который содержит параметр с типом из другой сборки. VD>Далее в другом проекте создается тип реализующий интерфейс и сразу же приводится к интервейсу. Но появляется это сообщение (плюс еще меседжбокс) и ничего не работает.
Попробую воспроизвести на обоих компиляторах. А вот с меседжбоксом странно — у меня он еще ни разу не выскочил.