02.09.2009, 22:58 | #21 |
Участник
|
А что, разве такое присваивание заставляет увеличиться счетчик ссылок не только у объекта b, но и у всех связанных с ним объектов ? Мне казалось что достаточно проинкрементировать счетчик ссылок только для b.
|
|
03.09.2009, 00:26 | #22 |
Участник
|
|
|
03.09.2009, 09:11 | #23 |
Участник
|
|
|
03.09.2009, 10:07 | #24 |
Участник
|
Если два объекта циклически ссылаются друг на друга как они соберутся если есть только счетчик ссылок.
X++: ... a,parmB(B); b.parmA(a); ... |
|
03.09.2009, 10:34 | #25 |
Участник
|
Цитата:
Интересно конечно как сборщики мусора решают такие проблемы. В аксапте такие взаимные ссылки сплошь и рядом. Сходу вспоминается форма, датасорс и таблица датасорса, от каждого можно добраться по ссылкам к каждому, взаимные ссылки тоже легко сделать, особенно когда в форме анализируется args().caller() и запоминаются ссылки. К счастью, судя по поведению аксапты, эта проблема как-то решена и память не утекает. |
|
03.09.2009, 11:44 | #26 |
Участник
|
>>> Интересно конечно как сборщики мусора решают такие проблемы.
Ходят по ссылкам маркируют то, что используется, убирают остальное. Правда обычно они это делают когда компу нечем заняться или память кончается. А в аксапте, гарантируется, что мусор собирается сразу же после того, как он образуется. Благодаря этому в AsciiIO нет метода Close или Dispose - файл закрывается сразу же как только ссылки на объект пропадают. А в C# пришлось сделать специальную конструкцию using. А еще в аксапте сборщик мусора распределенный - клиент и сервер - и циклы могут быть кроссзвеньевые. |
|
|
За это сообщение автора поблагодарили: Logger (1). |
03.09.2009, 18:04 | #27 |
Участник
|
У меня, если честно, сложилось ощущение, что участниками форума то ли ролик был досмотрен не до конца, то ли английский с датским акцентом так подействовал, но в результате отнюдь не все основные мысли, прозвучавшие в презентации, были услышаны. Тем не менее, по-моему, озвучено было гораздо больше, чем просто то, что датские ребята из команды X++ научились генерить из p-кода IL-код. В связи с этим позволю себе опубликовать вольный перевод того, что говорилось в презентации. Сразу извиняюсь за качество иллюстраций - это скриншоты из видео, которое на channel9 было обозначено как наилучшее по качеству из имеющихся вариантов. Кроме того, я позволил себе кое-где оставить свои комментарии, а также выделить те мысли, которые мне показались важными.
Peter Villadsen: ...До недавнего времени средства разработки в Dynamics AX и язык X++ с его встроенными возможностями работы с СУБД представляли собой один из наиболее выдающихся пакетов разработки в своей области. Однако, теперь остальной мир уже догнал их; теперь в .NET появился LINQ, обладающий выдающимися возможностями и построенный на очень впечатляющих теоретических разработках. Раньше у нас не было таких средств разработки, но теперь они появились, и это одна из причин, почему мы решили, что пора двигаться в сторону мира управляемого кода. Люди часто повторяют: надо стоять на плечах гигантов, и, думаю, в вашей студии это звучало не раз, но я чувствую, что это именно то, что мы должны делать. Нам не следует самим нести все затраты, связанные с поддержкой и развитием всей инфраструктуры, когда есть такие отличные вещи, как .NET, и Visual Studio, и LINQ. И наша разработка, которую мы сегодня представим, - это один из первых шагов в этом направлении. Но давайте перейдем к рассмотрению работы. Изначально есть исходный код на X++; он обрабатывается компилятором X++, который на входе получает этот исходный код плюс некоторую дополнительную информацию, а именно метаданные, которые хранятся в приложении. Это ключевой момент: в X++ используется большой набор метаданных, так что если мы, к примеру, ссылаемся на таблицу, то при компиляции, если такая таблица не существует, мы сразу получаем сообщение об ошибке. И информация обо всем, что мы создаем, сохраняется в виде метаданных, так что у компилятора X++ на этапе компиляции кода есть большой объем дополнительной информации. Но давайте продолжим. Компилятор при обработке исходного кода создает большой объем выходной информации - это и перекрестные ссылки, и различные диагностические сообщения, но основным результатом успешной компиляции является p-код. Его концепция, думаю, многим известна: это высокоуровневый язык ассемблера, предназначенный для выполнения не какой-либо аппаратной платформой, а программным интерпретатором, и в ядре Dynamics AX есть интерпретатор, читающий этот p-код и выполняющий на его основе те или иные действия. Ведущий: Это отличная архитектура в случае, если у вас есть и другие языки программирования вне вашей системы, на выходе которых получается такой же p-код, который может выполняться тем же интерпретатором. То же мы имеем и в .NET [ подразумевается CLR, прим.перев.]: разработка ведется на различных языках, но на выходе получается все тот же IL-код. Как же в этом плане дела обстоят с вашей системой? Peter Villadsen: В нашем случае все совсем не так: и весь стек разработки приложений на X++, и p-код, и его интерпретатор, и отладчик - это собственные, закрытые разработки, спецификации которых никогда не раскрывались. Так вот, на данный момент в нашем приложении появились опеределенные проблемы, связанные с тем, что разработчики начали использовать X++ так, как мы совершенно не расчитывали на момент разработки языка. И в X++, и в .NET мы можем создавать объекты, которые используются некоторое время, и затем занимаемая ими память освобождается, но коренное отличие .NET - в недетерминированной сборке мусора: когда ссылок на объект больше нет, вы не знаете точно, когда именно он будет уничтожен, и в большинстве случаев вас не должно это волновать. В X++ же все совсем иначе: здесь сборка мусора детерминирована, так что как только объект перестает использоваться приложением, он немедленно уничтожается. Во многом благодаря этому стала возможной реализация клиент-серверной архитектуры: объект на одном уровне может ссылаться на объект, находящийся в совершенно другом месте, в Австралии или на Северном полюсе, без разницы - для этого и понадобилась детерметнированная сборка мусора. Но такой подход проигрывает в плане масштабируемости: когда у вас сотни тысяч, скажем, полмиллиона используемых объектов, то добавление еще одного объекта и вставка его в поддерживаемый граф объектов занимает непропорционально много времени. Мы столкнулись с этой проблемой и искали пути ее решения; одним из подходов была реализация недетерминированной сборки мусора в рамках существующего ядра системы, но это было бы совсем непросто по ряду технических причин. И тут мы подумали: но ведь то, что нам нужно, - это именно то, что делает .NET [ тут снова подразумевается CLR, прим.перев.], так что можно забыть о переделке интерпретатора, ведь .NET делает это лучше, нежели мы сами смогли бы реализовать, так что давайте перенесем выполнение кода в .NET. С другой стороны, наша команда X++ довольно малочислена, и мы знали, что нам никогда бы не выделили финансирование на полное переписывание компилятора под создание управляемого кода, от начала до конца, поэтому мы решили пойти на небольшой компромис, что в конечном счете доказало свою эффективность. Мы создали инструмент, который берет на входе p-код и генерирует на его основе IL-код. Таким образом, весь стек инструментов разработки, который у нас есть и который использовался и тестировался на протяжении 15 лет, остается в полной неприкосновенности, в нем не меняется ни строчки исходного кода. Так что нам не нужно проводить обширное тестирование всего кода X++ во всем мире на совместимость с нашей разработкой. Кроме того, мы оставляем возможность продолжать разработку нового кода на X++, как и прежде. Ведущий: Однако, теперь вы попадаете в другой мир, теперь вы работаете с недетерменированной сборкой мусора, и у вас, к примеру, могут возникнуть проблемы, связанные с воскрешением объектов [ сборщик мусора в CLR воскрешает считающиеся уже мертвыми объекты, которые требуют завершения, чтобы вызвать их метод Finalize(), после чего эти объекты умирают навсегда, прим.перев.]. Представьте, что объект на сервере вдруг воскресает, и в этот момент приходит вызов от клиента... Что вы собираетесь делать с подобными проблемами? Peter Villadsen: Дело в том, что мы не пытаемся моделировать тут те возможности клиент-серверного взаимодействия, которые сейчас поддерживаются ядром Dynamics AX. В X++ у вас может быть объект на одном уровне (клиенте или сервере), который ссылается на объекты на другом уровне и вызывает методы этих объектов, и так далее [ это в обсуждении выше называлось chatiness? прим.перев.]. По целому ряду причин это плохая модель. Мы в любом случае хотим уйти от этой модели, потому что не хотим поддерживать слишком много информации о состоянии на каждом из уровней (клиенте и сервере). Мы, напротив, хотим прийти к более облегченной модели, как, например, модель на базе веб-сервисов, где не было бы подобных недостатков. Таким образом, код, который мы переводим в IL, будет в общем случае выполняться на одном уровне (серверном или клиентском). Я хотел бы вернуться к вашему комментарию по поводу p-кода. Возможно, наиболее значительным для нас было осознание того, что уровни абстракции обработке p-кода и IL-кода очень и очень схожи: и тут, и там используются стековые машины со схожим уровнем абстракции осуществляемых операций и схожей структурой, которые помещают на вершину стека результат последней операции (в частности, возвращаемое значение функции) и т.д. Так что мы модумали, что можем обойтись достаточно простой логикой преобразования p-кода в IL, и с этого, собственно, начался этот проект. Все оказалось более чем реально. Gustavo Plancarte: Я также хотел бы сказать кое-что касаемо взаимодействия внешних управляемых приложений с Dynamics AX. Сейчас они взаимодействуют через Business Connector .NET, который уже, в свою очередь, взаимодействует с интерпретатором p-кода. Теперь же, за счет преобразования p-кода X++ в IL, такие системы смогут напрямую взаимодействовать с управляемым кодом приложения Dynamics AX. Peter Villadsen: Да, это одно из преимуществ, которые мы получаем, но это все пока - отдаленные перспективы. Нам пока сложно говорить о том, в какой версии Dynamics AX все это появится, поскольку помимо технических есть еще множество вопросов, связанных с планами развития, маркетингом и т.д. Но вернемся к обсуждению представленной технологии. Позвольте мне продемонстрировать, как это работает. Итак, у менять есть класс с одним простым методом. Этот метод не делает никаких сложных вычислений или чего-то такого - он нужен лишь для демонстрации основной идеи. Метод называется functionTest(), у него есть параметр ppp, у него есть строковая переменная, которой присваивается метка, во время выполнения преобразуемая в локализованную строку, здесь также есть регистронезависимое сравнение строк, есть цикл while и так далее. Итак, в меню Add-in у меня есть небольшая примочка, называется "Dump to XML", я запустил ее, и вот теперь у меня есть XML-представление данного конкретного класса. Зачем нам вообще нужно XML представление? Об этом уже говорилось ранее, тем не менее: XML нужен, чтобы отделить генерацию IL-кода от метаданных, за которыми приходилось бы лезть каждый раз в базу данных [NB! вспомним про обещанную миграцию метаданных из aod-файлов в БД - для людей из команды X++ это уже объективная реальность, прим.перев.], кроме того, XML является хорошим средством, позволяющим людям представить, что именно происходит. И вот, как, собственно, выглядит сгенерированный XML-файл: Итак, посмотрим вот сюда. Вот это functionTest(), вот локальные переменные, вот это - указатель this, вот - первый параметр, это - остальные переменные. Ниже, в секции Linemap у нас содержится информация о соответствии смещений в p-коде и строк исходного кода; отладчик Dynamics AX использует эту информацию, так же как отладчик из Visual Studio использует для сборок .Net pdb-файлы. Так что вы можете установить точку останова в коде, и отладчик будет знать, по какому смещению в p-коде следует прервать выполнение. Далее, у нас есть имена переменных, которые мы можем увидеть здесь, this идет первым, ppp - второй. А теперь интересный момент: вот здесь в XML у нас также представлен p-код, и мы можем увидеть знакомые вещи, строковые литералы, и в исходном коде, и в p-коде встречается строка "length is", вот "hello"... В общем, это представление p-кода, как его генерирует компилятор. Впрочем, должен заметить, что эти XML-файлы вовсе не предназначены для восприятия человеком, они нужны лишь в качестве исходных данных для инструмента, который мы хотим продемонстрировать. Мы берем эти исходные XML-файлы, пропускаем их через нашу программу и на выходе получаем IL-код. Работу самой программы преобразования я показывать не буду, посколько это не очень зрелищно, но хочу показать, что получилось на выходе: вот здесь у меня дизассемблированный IL-код, который я получил, открыв выходной файл в Reflector'е. Вот functionTest(), здесь справа вы можете увидеть сгенерированный для нее IL-код, и если вы посмотрите на исходный p-код, то увидите, насколько они схожи. То, что мы делаем, - это не "высшая математика", это даже близко не стоит по сложности с процессом компиляцией исходного кода, скорее, это почти механическое преобразование, основанное на определенных шаблонах кода. Зачем же все-таки понадобились промежуточные XML-файлы, если все необходимые данные и так есть в наличии? Их использование было продиктовано желанием отделить код доступа к матаданным приложения Dynamics AX от кода, который на основе этих данных и p-кода генерит IL-код, - чтобы не надо было лезть в метаданные каждый раз, когда мы хотим осуществить это преобразование. В принципе, мы могли бы реализовать генератор IL-кода так, чтобы вообще не использовать промежуточные XML-файлы. Однако, преобразованием в MSIL занимается написанный нами управляемый код, в то время как весь стек, связанный с получением метаданных, p-кода, исходников на X++ [т.е. ядро Аксапты, прим.перев.], написан на C++, и нам просто не хотелось возиться с кодом C++ без необходимости. Поэтому мы решили работать с промежуточными XML-файлами - это требует меньше кода на C++ и лучше контролируемо с точки зрения разработки. А теперь с помощью Reflector преобразуем полученный IL-код в исходный код на C#. И вот теперь вы можете увидеть, насколько исходный вариант на X++ и код на C# похожи. Вызов print() был преобразован в вызов PrintStr(), цикл while вполне ожидаемо был преобразован в цикл while в C#, a += i (увеличение a на значение i) было преобразовано в a = i + a, просто потому что компилятор так генерирует код, и так далее. Теперь поговорим немного о реализации. Для тех, кто не знаком с X++, я хотел бы привести несколько примеров, как код выполняется клиентом. Вот здесь мы создаем под отладчиком экземпляр класса SubLedgerJournalAsync и вызываем его метод. В отдладчике Dynamics AX вы видите стек вызовов, локальные переменные, если по ходу выполнения войти (step into) в метод, то вот тут мы увидим табличный буфер PurchTable, в котором можно увидеть значения соответствующих полей, и т.д. А теперь посмотрим то же самое, только в отладчике Visual Studio: Gustavo Plancarte: Теперь мы можем выполнять WCF веб-сервисы, вы видите у класса TestClass атрибут ServiceContract - стандартный атрибут WCF. Справа вы можете увидеть, что я добавил в проект ссылку на сборку Dynamics.Ax.Application, содержащую код всех классов и таблиц, который в "обычном" приложении Dynamics AX написан на X++ (эта сборка занимает целых 64 мегабайта!). Также у меня открыт файл xpp с исходным кодом на X++, где у меня установлена точка останова; вы видите, что здесь нет подстветки синтаксиса, потому что это всего ли демонстрация. Теперь я подключусь отладчиком к AOS'у, используя пункт меню Attach to Process и запущу выполнение моего клиентского приложения; это простой клиент WCF... И вот мы достигли первой точки останова, это пока код C#, ничего интересного, но если мы "зайдем" (step into) внутрь вызываемого метода, то окажемся в коде X++, т.е. мы уже отлаживаем код X++ в Visual Studio! Вы можете увидеть стек вызовов, локальные переменные, запись PurchTable со значениями отдельных ее полей. Вы видите, что через аргумент _purchId передано определенное значение, но мы можем изменить его в отладчике. И вот мы проходимся по коду метода PurchTable::find(), вот мы выполнили select и видим, что значения полей табличной переменной PurchTable изменились в соответствии со значениями, выбранными из БД. Мы можем перейти в контексты методов, находящихся выше по стеку вызовов, и посмотреть значения локальных переменных в этих методах. Кроме того, как и ожидалось, мы можем указать точку в коде выше по стеку вызовов, чтобы отладчик продолжил выполнение кода, пока мы не "выйдем" (step outside) до этой точки в коде. Таким образом, мы получаем все преимущества Visual Studio и .NET, можно сказать, бесплатно. Вы видели, как мы отлаживали код X++ в Visual Studio, о чем раньше нельзя было и мечтать, но теперь мы выполняем IL-код, а отладчику VS без разницы, как этот IL-код был получен, покуда он знает, какие исходные файлы ему соответствуют. В ходе процесса преобразования мы также генерируем pdb-файлы. Так что инструмент, который мы разработали, является полнофункциональным и прекрасно справляется со своими задачами. Ведущий: Что замечательно - мы теперь уже не обязаны использовать X++... Peter Villadsen: Да, мы уже думали об этом. В частности, мы думали о том, чтобы генерировать из p-кода исходный код на C#, и нам это вполне под силу. И это дает нам возможность полностью отказаться от X++: давайте просто нажмем на кнопку и транслируем 98% имеющейся бизнес-логики в корректно работающий код на C#; затем мы можем посадить за работу армию программистов, и через месяц они доведут этот показатель до 100%, и тогда X++ уйдет в историю. Консалтинговые компании, ISV, компании, внедрившие Dynamics AX, - все те, кто ищут разработчиков для доработки приложения Dynamics AX, уже не будут говорить кандидатам: "...только вам придется еще выучить новый язык программирования, называемый X++", нет, вместо этого они смогут говорить: "вы будете работать с .NET в привычной среде разработки, это будет вкладом в вашу карьеру, все, чем вы будете заниматься у нас, вы затем сможете применить и в других компаниях". По-моему, это наилучший сценарий, который только можно вообразить. Ведущий: Впрочем, это не значит, что X++ исчезнет как таковой. Это DML, он сможет остаться в своей нише, возможно, он эволиционирует в управляемый (managed) X++. Peter Villadsen: Фактические то, что мы сделали, это и есть управляемый X++, потому что из исходного кода на X++ вы получаете управляемый IL-код. Ведущий: Я имел в виду аналогию с Managed C++, где вы можете "встраивать" объекты с управляемым кодом в ваш исходный неуправляемый код. Peter Villadsen: Что самое интересное - мы уже сделали это в X++: мы реализовали возможность использования объектов управляемого приложения на ряду с "родными" объектами приложения Dynamics AX. Я могу ссылаться из X++ на что-ибудь вроде System.IO.BufferedStream, и это будет прекрасно работать за счет уже реализованных возможностей среды времени выполнения: корректно будет работать сборка мусора, учет ссылок на объект, чтобы он сохранялся в памяти, пока он используется, и все прочее - это уже работает. Но при этом есть несколько ограничений, например, совсем не поддерживаются дженерики (generics) и кое-что еще. Ведущий: И еще ключевое слово dynamic, лямбда-функции... В любом случае, то, что есть в X++ - это здорово, и 15 лет назад альтернативы такой реализации, наверно, не было, но теперь мы живем в другом мире, где никому не охота учить новый DSL, который не используется нигде, кроме одной-единственной системы (Ms Dynamics AX, в данном случае), так что ваша разработка имеет большое значение. Peter Villadsen: Правда, стоит отметить еще один момент: MorphX в Dynamics AX - это по сути среда быстрой разработки приложений (RAD), здесь вы можете работать с небольшим участком кода, изменить что-то, тут же запустить на выполнение, увидеть, что надо было указать другой параметр, снова изменить, запустить - и все это происходит очень быстро. К сожалению, при работе с C# мы пока не достигли такой скорости. Когда X++ транслируется в p-код, обрабатываемый интерпретатором, от запуска кода на выполнение до получения результатов могут пройти буквально доли секунды; когда же мы дополнительно транслируем p-код в MSIL, достичь такой скорости реакции системы пока не удается. И это - одно из обстоятельств, с которым мы пытаемся бороться, хотя, возможно, нам просто надо будет научиться с этим жить. Ведущий: Можно также провести аналогию с VB.NET, разработка приложений на котором куда больше соответствует понятию RAD, нежели разработка на C#. И VB.NET должен быть средой быстрой разработки приложений, потому что это одно из его преимуществ для разработчиков. Но, возможно, ситуация с C# и с управляемым X++ изменится к лучшему, потому что уже сейчас в C# есть фоновая компиляция кода по мере его ввода в редакторе, и вы сразу можете увидеть ошибки или опечатки. Что ж, замечательная презентация, посмотрим, как все это будет развиваться дальше. Надеюсь, когда вы продвинитесь вперед, мы снова соберемся сдесь и поговорим об этом еще раз. Последний раз редактировалось Gustav; 14.05.2010 в 16:57. Причина: ничего, что я вставил пустые строки перед репликами? |
|
|
За это сообщение автора поблагодарили: mazzy (15), raz (10), belugin (15), wb (1), AlexeyS (2), Logger (9), lev (5), tricky (1), apanko (4), Krash (1), brahma (1), _scorp_ (5), asinus (0), Evgeniy_R (1). |
03.09.2009, 18:22 | #28 |
Участник
|
chatiness то когда вместо одного большого куска данных синхронно передается много маленьких.
Типа вместо: serverObect.addList(list.pack()); Делается: serverObjext.addElement(a1); serverObjext.addElement(a2); serverObjext.addElement(a3); при каждом вызове надо передеть данные по сети и подождать пока вернется подтверждение что они переданы => общее время возрастают. То есть клент место того, чтобы сказать скразу что ему нужно от сервера, начинает с ним "болтать" |
|
14.05.2010, 12:01 | #29 |
Участник
|
При установке оценки рука дрогнула. Правильно +10
|
|
24.08.2010, 13:25 | #30 |
Участник
|
|
|
24.08.2010, 17:11 | #31 |
Участник
|
Я такого не встречал
|
|