среда, февраля 05, 2014

Delphi. Ненависть 2. 64-битная версия

Пост-продолжение Delphi. Ненависть 2.

------------------------------ Delphi XE2 Update 4 Hotfix 1 x64:
Project1.dpr.68: Utils.Namespace.CompareString(S1, S2);
0000000000426680 488D4D58         lea rcx,[rbp+$58]
0000000000426684 488B15BDEB0000   mov rdx,[rel $0000ebbd]
000000000042668B E86020FEFF       call @UStrLAsg
0000000000426690 488D4D50         lea rcx,[rbp+$50]
0000000000426694 488B15B5EB0000   mov rdx,[rel $0000ebb5]
000000000042669B E85020FEFF       call @UStrLAsg
00000000004266A0 488B4D58         mov rcx,[rbp+$58]
00000000004266A4 488B5550         mov rdx,[rbp+$50]
00000000004266A8 E82349FFFF       call CompareStr
Project1.dpr.69: Utils.Namespace.SameString(S1, S2);
00000000004266AD 488D4D48         lea rcx,[rbp+$48]
00000000004266B1 488B1590EB0000   mov rdx,[rel $0000eb90]
00000000004266B8 E83320FEFF       call @UStrLAsg
00000000004266BD 488D4D40         lea rcx,[rbp+$40]
00000000004266C1 488B1588EB0000   mov rdx,[rel $0000eb88]
00000000004266C8 E82320FEFF       call @UStrLAsg
00000000004266CD 488D4D38         lea rcx,[rbp+$38]
00000000004266D1 488B5548         mov rdx,[rbp+$48]
00000000004266D5 E81620FEFF       call @UStrLAsg
00000000004266DA 488D4D30         lea rcx,[rbp+$30]
00000000004266DE 488B5540         mov rdx,[rbp+$40]
00000000004266E2 E80920FEFF       call @UStrLAsg
00000000004266E7 488B4D38         mov rcx,[rbp+$38]
00000000004266EB 488B5530         mov rdx,[rbp+$30]
00000000004266EF E8DC48FFFF       call CompareStr
------------------------------ Delphi XE5 Update 2 x64:
Project1.dpr.68: Utils.Namespace.CompareString(S1, S2);
0000000000426F94 488D4D78         lea rcx,[rbp+$78]
0000000000426F98 488B1581F20000   mov rdx,[rel $0000f281]
0000000000426F9F E88C23FEFF       call @UStrLAsg
0000000000426FA4 488D4D70         lea rcx,[rbp+$70]
0000000000426FA8 488B1579F20000   mov rdx,[rel $0000f279]
0000000000426FAF E87C23FEFF       call @UStrLAsg
0000000000426FB4 90               nop
0000000000426FB5 488B4D78         mov rcx,[rbp+$78]
0000000000426FB9 488B5570         mov rdx,[rbp+$70]
0000000000426FBD E86E34FFFF       call CompareStr
0000000000426FC2 89453C           mov [rbp+$3c],eax
0000000000426FC5 90               nop
0000000000426FC6 488D4D78         lea rcx,[rbp+$78]
0000000000426FCA E8411EFEFF       call @UStrClr
0000000000426FCF 488D4D70         lea rcx,[rbp+$70]
0000000000426FD3 E8381EFEFF       call @UStrClr
Project1.dpr.69: Utils.Namespace.SameString(S1, S2);
0000000000426FD8 488D4D58         lea rcx,[rbp+$58]
0000000000426FDC 488B153DF20000   mov rdx,[rel $0000f23d]
0000000000426FE3 E84823FEFF       call @UStrLAsg
0000000000426FE8 488D4D50         lea rcx,[rbp+$50]
0000000000426FEC 488B1535F20000   mov rdx,[rel $0000f235]
0000000000426FF3 E83823FEFF       call @UStrLAsg
0000000000426FF8 488D4D68         lea rcx,[rbp+$68]
0000000000426FFC E80F1EFEFF       call @UStrClr
0000000000427001 488D4D60         lea rcx,[rbp+$60]
0000000000427005 E8061EFEFF       call @UStrClr
000000000042700A 488D4D48         lea rcx,[rbp+$48]
000000000042700E E8FD1DFEFF       call @UStrClr
0000000000427013 488D4D40         lea rcx,[rbp+$40]
0000000000427017 E8F41DFEFF       call @UStrClr
000000000042701C 90               nop
000000000042701D 488D4D68         lea rcx,[rbp+$68]
0000000000427021 488B5558         mov rdx,[rbp+$58]
0000000000427025 E80623FEFF       call @UStrLAsg
000000000042702A 488D4D60         lea rcx,[rbp+$60]
000000000042702E 488B5550         mov rdx,[rbp+$50]
0000000000427032 E8F922FEFF       call @UStrLAsg
0000000000427037 90               nop
0000000000427038 488B4D68         mov rcx,[rbp+$68]
000000000042703C 488B5560         mov rdx,[rbp+$60]
0000000000427040 E8EB33FFFF       call CompareStr
0000000000427045 894534           mov [rbp+$34],eax
0000000000427048 90               nop
0000000000427049 488D4D68         lea rcx,[rbp+$68]
000000000042704D E8BE1DFEFF       call @UStrClr
0000000000427052 488D4D60         lea rcx,[rbp+$60]
0000000000427056 E8B51DFEFF       call @UStrClr
000000000042705B 837D3400         cmp dword ptr [rbp+$34],$00
000000000042705F 0F94C0           setz al
0000000000427062 88453B           mov [rbp+$3b],al
0000000000427065 90               nop
0000000000427066 488D4D58         lea rcx,[rbp+$58]
000000000042706A E8A11DFEFF       call @UStrClr
000000000042706F 488D4D50         lea rcx,[rbp+$50]
0000000000427073 E8981DFEFF       call @UStrClr
0000000000427078 488D4D68         lea rcx,[rbp+$68]
000000000042707C E88F1DFEFF       call @UStrClr
0000000000427081 488D4D60         lea rcx,[rbp+$60]
0000000000427085 E8861DFEFF       call @UStrClr
000000000042708A 488D4D48         lea rcx,[rbp+$48]
000000000042708E E87D1DFEFF       call @UStrClr
0000000000427093 488D4D40         lea rcx,[rbp+$40]
0000000000427097 E8741DFEFF       call @UStrClr
------------------------------ FreePascal 2.7.1. x64:
project1.lpr:68                           Utils.Namespace.CompareString(S1, S2);
000000010000158A 488b157fda0100           mov    0x1da7f(%rip),%rdx        # 0x10001f010
0000000100001591 488b0d68da0100           mov    0x1da68(%rip),%rcx        # 0x10001f000
0000000100001598 e843e40000               callq  0x10000f9e0 <SYSUTILS_$$_COMPARESTR$ANSISTRING$ANSISTRING$$LONGINT>
project1.lpr:69                           Utils.Namespace.SameString(S1, S2);
000000010000159D 488b156cda0100           mov    0x1da6c(%rip),%rdx        # 0x10001f010
00000001000015A4 488b0d55da0100           mov    0x1da55(%rip),%rcx        # 0x10001f000
00000001000015AB e830e40000               callq  0x10000f9e0 <SYSUTILS_$$_COMPARESTR$ANSISTRING$ANSISTRING$$LONGINT>
00000001000015B0 85c0                     test   %eax,%eax
00000001000015B2 0f94c0                   sete   %al

пятница, января 31, 2014

Firemonkey, которая гуляет сама по себе.

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

Воспроизведено на устройстве Huawei Ascend Mate, Android 4.1.2, ланчер EmotionUI 1.5.

Проект на котором очень хорошо воспроизводятся эти эффекты можно взять тут (прямая ссылка).

На видео видно, что несмотря на фантомные срабатывания, когда к устройству даже не прикосаешься, само приложение никак не реагирует на прикосновения пальца (это бывает не всегда, и иногда оно таки реагирует). Более того, перестают реагировать даже системные навигационные кнопки. Все это безобразие можно прекратить только нажатием аппаратной кнопки выключения.

Нужно заметить, что ни в одном другом приложении, ни основанных на SDK, ни на NDK таких эффектов не наблюдается. К телефону вообще нет ни малейших претензий. Воспроизводится это только в Firemonkey-приложениях.

QC#122138

понедельник, января 20, 2014

Если хочешь быть здоров…

…закаляйся!

IMG_20140119_115636

IMG_20140119_115645

Уже пятый год, на Крещение, ходим с друзьями купаться. Вчера было здорово. Погода прекрасная: легкий морозец (-22 градуса) и едва заметный снежок.

понедельник, января 06, 2014

Delphi. Ненависть 2.

В посте Delphi. Ненависть. я показал как деградировал кодогенератор дельфей. Сегодня покажу еще раз, только уже с кодом на котором проблема воспроизводится.

воскресенье, декабря 29, 2013

Delphi XE5 Update 2. S.S.D.D.

Вот, наконец-то, и я добрался (несколько припозднился, но на то были причины) до ощупывания Delphi с поддержкой Android. С самого начала было ясно, что качественной эта поддержка не будет, а потому нет смысла сразу кидаться покупать какое-либо Android-устройство. Но в планах уже значиналось приобретение нового смартфона на замену дышавшей на ладан старенькой Nokia. С моделью я определился через несколько дней после выхода Delphi XE5 (стимул всё-таки), и как выяснилось практически сразу, с выбранной моделью у Delphi проблемы (точнее с графическим процессором используемом в данном аппарате). Но, телефон должен нравится мне, а не Delphi, поэтому выбора своего я решил не менять (хотя посматривал и на Lenovo K-900, но с тем у Delphi вообще фатальная несовместимость) и надеяться на скорый фикс этого бага. В Update 2 баг таки пофиксили. Ура. Тестируем новую обезьяну, ой, простите, теперь это уже FM Platform (не хухры-мухры, но попробуйте кроссплатформенно послать SMS’ку или погудеть виброй, так сразу поймете ценность этого “Platform” :))

суббота, октября 12, 2013

Кушайте, не обляпайтесь.

Сегодня в ридере появилась статья “Delphi штурмует Android. Беседуем с Всеволодом Леоновым о Delphi XE5” рассказывающая о победах и завоеваниях. Такое всегда интересно почитать. Я позволю себе процитировать оттуда небольшой фрагмент:

- Технологии FireMonkey уже несколько лет. Вроде все более менее становится стабильным и уже не так страшно применять новинку для продакшн приложений. По прошествии этого временного промежутка вы можете сказать, что технология удалась? Нашла ли она свою аудиторию и какие нововведения следует ожидать в обозримом будущем?

Что технология удалась, стало заметно, к сожалению, лишь сейчас, если мы смотрим на неё глазами разработчиков. Только сейчас программисты стали реально интересоваться Платформой приложений FM (бывшая FireMonkey), когда увидели всю её мощь для мобильной разработки под Android. И это несмотря на то, что архитектурно она была заложена и технологически реализована в релизе XE2. Например, российский проект www.sphere-online.ru – многоцелевая платформа онлайн-коммуникаций. Команда выбрала Платформу FM, т.к. изначально хотела сделать мульти-платформенное решение для Windows и Mac OS, причем с интерфейсом высшего качества. На следующем после XE2 релизе XE3 данная компания сделала мульти-платформенную систему, а что может быть лучшим доказательством успешности технологии, как ни реализация на её основе реального проекта!? Теперь данная команда благодарит сама себя за правильный выбор средства разработки в своё время и готовит мобильную поддержку.

 

В общем, я сходил по данной ссылке… Никакой многоцелевой платформы онлайн-коммуникаций там нет, есть редирект на онлайн-игру “Сфера-перерождение”. Думаю, ну мало-ли, может их сейчас принято называть многоцелевыми коммуникационными платформами. В общем, скачал клиент дабы посмотреть чего там на FMX наваяли. Оказалось, что FMX’ом там и не пахнет. Исполняемые модули, коих две штуки, собраны компилятором MS VC++, и россыпь dll’ей тоже ни коим боком к FMX не относится. Так то. А народ в комментариях радуется, дескать жива курилка. Хотел прямо там вопрос задать – что мол за дела - да у них для этого регистрироваться нужно. В общем вот. В меню сегодня лапша.

 

Обновление от 16.10.2013.

Так, похоже имела место быть чья-то невнимательность, из-за которой в статье была указана неправильная ссылка. А я уже успел о Всеволоде плохо подумать :) Спасибо Роману Янковскому за изыскания. Правильная ссылка вот http://www.sphere-live.com/ и там действительно коммуникационный софт с FMX-интерфейсом.

 

Но я же не зря ходил по тем ссылкам, я хотел посмотреть на интерфейс высшего качества о котором говорится в статье. Итак, кратко - под интерфейсом высшего качества имеется ввиду FMX-стиль “Jet” из Premium Style Pack (это тот, где все черное-черное). Кому-то сливающаяся чернота нравится, кому-то нет.

Теперь по порядку. Первый запуск на хостовой машине c Windows 7 x64 закончился ничем:

sphere_at_start_on_host

Следующие попытки я делал уже под виртуальной Windows 7 x86. Запуск прошел успешно. Но в окне регистрации, после выбора русского языка, снова сюрприз:

sphere_av

Дальше открывается основное окно с кучей элементов управления. Походив по меню (кстати, в этом стиле совершенно не понятно, какой пункт меню активен, а какой пассивен, т.е. какой может быть выбран, а какой нет) поймал еще один глюк (два одновременно открытых выпадающих меню):

sphere_gui

Потребление памяти на этом этапе составляло примерно 140MB, что довольно много для такого софта, особенно если учесть, что пользоваться я им даже не начал. Реакция интерфейса на действия пользователя по FMX-овски неспешная, если не сказать тормозная. Это уж точно не высший класс. В конце-концов приложение пришлось прибить т.к. при выходе случилось страшное (я долго ждал завершения, но так и не дождался):

sphere_at_exit

пятница, мая 10, 2013

Delphi. Ненависть.

Код (вызов представляющий собой каскад двух inlined методов):

xv.Initialize(bin.Instance);


Turbo Delphi 2006 Explorer генерирует:



XmlRpcDeserializerTest.pas.2634: xv.Initialize(bin.instance);
00526489 8D9524FFFEFF lea edx,[ebp-$000100dc]
0052648F 8D45E8 lea eax,[ebp-$18]
00526492 E88DA8FAFF call XmlRpcBinary.GetInstance
00526497 8B8524FFFEFF mov eax,[ebp-$000100dc]
0052649D 8945B0 mov [ebp-$50],eax
005264A0 A154784C00 mov eax,[$004c7854]
005264A5 50 push eax
005264A6 8D8558FFFFFF lea eax,[ebp-$000000a8]
005264AC B107 mov cl,$07
005264AE 8B55B0 mov edx,[ebp-$50]
005264B1 E89E37FAFF call XmlRpcValue.SetValueIntf


Delphi XE2 - XE4 генерирует:



XmlRpcDeserializerTest.pas.2634: xv.Initialize(bin.instance);
006C9E77 8D955CFFFEFF lea edx,[ebp-$000100a4]
006C9E7D 8D85C4FFFEFF lea eax,[ebp-$0001003c]
006C9E83 E8683DF6FF call XmlRpcBinary.GetInstance
006C9E88 8B9D5CFFFEFF mov ebx,[ebp-$000100a4]
006C9E8E 8D85E4FFFEFF lea eax,[ebp-$0001001c]
006C9E94 E8973FD4FF call @IntfClear
006C9E99 33C0 xor eax,eax
006C9E9B 55 push ebp
006C9E9C 684D9F6C00 push $006c9f4d
006C9EA1 64FF30 push dword ptr fs:[eax]
006C9EA4 648920 mov fs:[eax],esp
006C9EA7 8D85E4FFFEFF lea eax,[ebp-$0001001c]
006C9EAD E87E3FD4FF call @IntfClear
006C9EB2 33C0 xor eax,eax
006C9EB4 55 push ebp
006C9EB5 682D9F6C00 push $006c9f2d
006C9EBA 64FF30 push dword ptr fs:[eax]
006C9EBD 648920 mov fs:[eax],esp
006C9EC0 8D85E4FFFEFF lea eax,[ebp-$0001001c]
006C9EC6 8BD3 mov edx,ebx
006C9EC8 E87B3FD4FF call @IntfCopy
006C9ECD 33C0 xor eax,eax
006C9ECF 55 push ebp
006C9ED0 680D9F6C00 push $006c9f0d
006C9ED5 64FF30 push dword ptr fs:[eax]
006C9ED8 648920 mov fs:[eax],esp
006C9EDB A10C3B6200 mov eax,[$00623b0c]
006C9EE0 50 push eax
006C9EE1 8D85A0FFFEFF lea eax,[ebp-$00010060]
006C9EE7 B107 mov cl,$07
006C9EE9 8B95E4FFFEFF mov edx,[ebp-$0001001c]
006C9EEF E898C7F5FF call XmlRpcValue.SetValueIntf


Это п#$%&ц. Зарепортить не могу т.к. воспроизвести на другом коде не получается. Но подобное есть еще в паре мест, и тоже с разворачиванием inlined методов.

четверг, мая 02, 2013

Delphi XE4. Чем дальше, тем страшнее.

Кажется, у Embarcadero уже вошло в привычку выпускать сырые бета-версии и называть их релизами. Чтож, они испекли еще один. Судя по всему, делался он в дикой спешке – иначе объяснить настолько отвратительное качество просто нечем.

 

Firemonkey. Одно лечим, другое калечим.

В обезьяне произошли некоторые приятные изменения – анимация стала работать заметно лучше – и дело тут не в увеличенном вдвое фреймрейте - спасибо разделяемому RTTI-кэшу. Однако, для отсчетов временных интервалов по прежнему используется тип с малой точностью, поэтому на системах с большим аптаймом снова будут рывки.

Padding и Margins поменяли поведение на противиположное. Некоторые контролы переехали в другое пространство имен. В общем, переделки пользователям FMX, если такие отчаянные есть, обеспечены.

Формы FMX разучились сворачиваться в панель задач – клик по кнопке в панели ни к чему не приводит. Сворачивать можно только кнопкой в заголовке окна, но при этом форма сворачивается не в панель задачь, а в левый нижний угол над панелью.

В дизайнере не меняется шрифт у TText и TLabel. То есть изменение размера действует, а вот изменение названия нет.

Поправили TPath, теперь он справляется с довольно сложными контурами. Однако, TPath.WrapMode = pwFit работает некорректно. Сглаживание контуров под XP так и не сделали (она хоть и старушка, но все же третья по популярности ОС). Кстати, со сглаживанием вообще странность. В редакторе свойства TPath.Data контур оказывается сглаженным:

data_editor_normal

но стоит изменить размер окна, как сглаживание исчезает:

data_editor_resized

Поломали TreeView. Если у дерева вызвать метод TreeView.ExpandAll список узлов превращается в кашу (слева пример собранный в XE3, справа в XE4):

expanded_treeviews

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

пятница, декабря 07, 2012

Блеск и нищета Firemonkey²

Блеск

В Delphi XE3 у Firemonkey появилась возможность стилизовать неклиентскую область окон приложения. Для этого используются новые имена стилей: для Windows это windowborderstyle и toolwindowstyle, для Mac OS используется единственный стиль macborderstyle. Информации, как создать такие стили нет, во всяком случае я не нашел, поэтому всё что будет написано дальше является результатом исследования кода класса TWindowBorder и его потомков под каждую платформу. В общем, можно сказать, что создать собственный стиль неклиентской области дело довольно простое. Стиль подразумевает наличие некоторых предопределенных элементов (например ‘client’ отвечает за клиентскую область окна, а ‘title’ за его текстовый заголовок) из которых формируется внешний вид окна. Так же имя элемента стиля отвечает за обозначение действия какой-либо области окна. Например элементы c именем стиля ‘left’ и ‘right’ отвечают за изменение горизонтального размера окна, а ‘caption’ за его перемещение (элементов с одинаковым именем стиля может быть несколько, что в результате даст несколько зон отвечающих за одно и то же действие) То есть при клике на этих элементах будет выполняться соответствующее им действие. В общем, кто имел опыт работы с WinAPI, в части обработки оконных сообщений, наверняка провели параллель с такой вещью, как HITTEST, и оказались правы – механизм работает один-в-один. Это был блеск. Теперь о нищете.

Нищета

Воодушевившись открывшимися новыми возможностями я решил сделать стиль имитирующий окна Mac OS X Leon. За основу был взят незамысловатый скриншот:

pic14

и еще несколько изображений окон, где присутствовали кнопки в заголовке окна. Я не ставил себе целью сделать сразу полнофункциональный стиль, для начала хотелось добиться схожести с оригиналом. Вооружившись дизайнером стилей и в очередной раз убедившись, что пользоваться оным невозможно, было решено дизайнить стиль прямо на форме (ведь любой стиль это просто набор компонентов). Затем с формы стиль был скопирован в файл macosx.style и загружен в компонент класса TStyleBook, который был назначен форме. В редакторе стилей созданный стиль выглядел вот так:

styledesigner

Сглаживания на кнопке нет т.к. делал я все под Windows XP, а у Firemonkey на этой ОC сглаживание не работает (работало до Delphi XE2 Update 4 hotfix 1, но хотфиксом его сломали да так и не починили). Для создания эффекта тени пришлось генерировать картинку в GIMP т.к. стандартный эффект TShadowEffect такую тень отрисовать не способен (при значении свойства Softness равном единице тень уже имеет видимую глазу структуру, а при значениях больше единицы и вовсе превращается в клетчатое пятно). Но с картинкой возникает проблема. При изменении размера окна тень должна растягиваться без артефактов поэтому просто масштабировать картинку нельзя, её нужно делить на области: четыре имеющих постоянный размер (расположены в углах), две растягивающиеся горизонтально и две растягивающие вертикально. Итого получается восемь частей. Каждую такую часть можно было представить компонентом TImage в который был бы загружен файл соответствующей части изображения. Однако, в Delphi XE3, для поддержки растровых стилей Firemonkey, появился класс TSubImage способный отрисовывать указанную область изображения на которое он ссылается. Это удобнее, чем делать множество файлов. Но, этот класс не доступен в дизайнере, поэтому мне пришлось установить в IDE пакет регистрирующий его. В общем, после некоторого непредвиденного траха с пакетом, тень была готова. Заголовок с кнопкой и клиенсткую область сделать труда не составило. Хотя нет, подобрать градиент для кнопки было сложно т.к. элементы выделения (белые кружочки для изменения размеров) полностью перекрывали маленькую кнопку и изменяющийся градиент было не видно :) В результате схожесть не попиксельная, но довольно близка к оригиналу. Итак, стиль готов, первый запуск:

styledwindowblackshadow

Легкое недоумение. Пробую максимизировать окно, оно максимизируется так, как будто тень является клиентской областью т.е. я вижу не распахнутую на весь экран клиентскую область, а клиентскую область в окружении черной рамки. Хорошо, с максимизацией разберемся как нибудь позже, но почему тень не прозрачная… Я же помню, что у меню были прозрачные тени. Ищу в файле стилей стиль для меню (menuviewstyle). Вижу, что тень сделана с помощью эффекта TShadowEffect, но место под неё зарезервировано с помощью свойств Margin и Padding у элементов стиля. Попробовал и я у своей тени выставить отрицательный Padding, вот что из этого вышло:

styledwindow

Тень совсем пропала, а кроме этого на каждое изменение размеров окна генерируется четыре исключительных ситуации EZeroDivide. В общем трюк не сработал. Начал смотреть, что же там происходит под капотом модуля FMX.Platform.Win отвечающем за взаимодействие с платформой Windows. А там все печально. Оказалось, что по изображению полученному отрисовкой стиля формируется регион (регион в терминологии Win32) и назначается окну. Всё, прощай прозрачная тень, прощайте сглаженные уголки окна и да здравствуют зазубрины :( Но, как же, тогда отрисовывается тень у меню? А для меню используются композитные окна (см. TFrom.Transparency). В общем, тоска зеленая :(

понедельник, декабря 03, 2012

iPhone “slide to unlock” animation средствами Firemonkey. DelphiXE2.

Как бы кто ни относился к Apple, одно признают все – эти парни умеют делать красиво. Их “красота” заключается в не пергруженных деталями интерфейсах и изысканных мелочах. Одной из таких мелочей является анимация элемента разблокировки экрана (кто не видел, погуглите slide to unlock animation). Как только вышла Delphi XE2 я сразу попробовал сделать подобный эффект средствами Firemonkey. Тогда, получив удовлетворительный результат, я не стал описывать его т.к. думал, что следующая версия Firemonkey позволит реализовать этот эффект не написав ни строчки кода. Этого, увы, не случилось. Более того, в Delphi XE3, классы TText и TLabel лишились свойства Fill, что сделало невозможным применение каких-либо вариантов раскраски текста. Поэтому публикую вариант для Delphi XE2.

Вот что у меня вышло:

spotlight_effect

Реализация очень простая. В качестве “раскраски” текста применяется битмап в который отрисовывается прямоугольник серого цвета с анимированным градиентом имитирующим пятно света. Все это делается в дизайнере, за исключением отрисовки контрола в битмап т.к. TBushGrab, являющаяся одним из вариантов использования кисти, корректно не работает.

 

Исходник и скомпилированный пример можно скачать тут.

пятница, сентября 28, 2012

Delphi XE3.FireMonkey: Фиксим рваную анимацию

О проблемах с анимацией в FireMonkey я уже неоднократно писал. Причина кроется в недостаточной точности используемого типа - Single. С переработкой FireMonkey на архитектуру сервисов, произошедшую в Delphi XE3, появилась возможность очень просто этот косяк пофиксить. В общем, фикс можно скачать отсюда.

 

p.s. Достаточно подключить модуль к проекту. Работает начиная с Delphi XE3. Будем надеяться, что с первым апдейтом этот фикс станет ненужен.

вторник, сентября 25, 2012

Delphi XE3.FireMonkey: куда ни кинь – всюду клин.

Это просто ужас какой-то – за что-бы ни взялся, ну просто все глючит :( После предыдущего подхода закончившегося серией QC-отчетов и серьезно охладившего пыл, сегодня решил еще поиграться с новым редактором стилей (о нем писать не буду – он ужасен. Даже элементарных действий по изменению Z-order для объектов нет, а Copy/Past умудряются глючить. Впрочем не удивительно, Крюков же говорил, что ему удобнее с текстовым представлением работать, видимо и нам нефиг расслабляться) и сделать небольшое т.н. gloat-logo наподобие такого:

firebird

Для этого я векторизовал в Inkscape изображение шлема с картинки для TLiveTile. Получилось довольно не плохо:

delphi_logo

А вот так это отображается посредством TPath:

dxe3

Для сравнения скриншот Delphi XE2 Update 4:

dxe2

В общем, пользоваться этим нельзя.

 

QC#109005

Update: 26.09.2012 11:07

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

воскресенье, сентября 09, 2012

Delphi XE3. Очередной сырой релиз Firemonkey.

Багу с анимацией не поправили, она как была рваная так таковой и осталась. Причины они, похоже, поняли. Типу Single, используемому для счетчика тиков таймера (и кому в голову такая идея пришла, для счетчика использовать нецелочисленный тип) не хватает точности если у системы большой аптайм. В IFMXTimerService.GetTick они заменили его на Extended, а вот в реализации класса TAnithread забыли.

ani_bug

QC#108614

 

TreeView стало сильно нагружать CPU. Для дерева с одной тысячей элементов загрузка доходит до 100% в состоянии покоя. Мне не понятно, они там вообще ничего не тестируют что-ли?

treeview_bug

QC#108615

 

Еще вылез косяк с пропадаением/мерцанием шейдерной тени в 3D. Но тут без репорта, ибо надоело.

 

Регрессию с отсутствием сглаживания на XP тоже не пофиксили, а ведь она висит с выхода XE2 Update 4 Hotfix 1.

 

Update: 20:17 09.09.2012

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

shadow_bug

QC#108620

 

Update: 23:46 12.09.2012

Удалось воспроизвести еще один косяк с эффектом тени. На TForm3D размещен прозрачный TLayer3D с объектом внутри. Объекту назначен эффект тени. Тень пропадает, когда активизируется другой шейдерный эффект (это, кстати, регрессия, на XE2 такого небыло):

shadow_bug2

QC#108719

четверг, августа 30, 2012

Lazarus 1.0. Релиз.

Свершилось. Lazarus 1.0 релизнулся. Поздравляем команду работавшую над этой замечательной средой со столь важной вехой. Буду постепенно адаптировать свои наработки под FreePascal, чтоб в перспективе полностью слезть с Delphi. Абракадабра, похоже, совсем берега потеряла.

среда, июля 18, 2012

Евангелисты врут. FireMonkey - отстой.

Вы, наверное, в курсе, что Embarcadero активно продвигает свое новое видение создания кроссплатформенного гуя – FireMonkey (они это называют фреймвоком, но для её нынешнего состояния это слишком круто звучит). В рунете анонсируется один конкурс за другим, проводятся вебинары, и пусть качество последних оставляет желать лучшего, но активность радует.  Теперь, собственно, к теме. В рамках последнего конкурса было предложено разработать какое-нибудь приложение для обучения. И вот вчера появилась очередная работа за авторством Евгения Чмеля (не знаю, склоняется эта фамилия или нет). В отличии от виденных ранее, простеньких “одноформочек”, тут была сделана попытка подергать обезьяну за все конечности: стилизация, 3D, шейдерные эффекты (о GPU accelerated graphics очень любят говорить евангелисты Embarcadero :)) ). Давайте посмотрим, что из этого вышло. Для тех, кто не смотрел вебинары сделаю маленькое отступление. На одном из вебинаров, евангелист Embarcadero, Всеволод Леонов рассказал душещипательную историю о том, как ему пришлось “компьютер перегрузить, конкретно, жестко” (это цитата), из-за того, что Silverlight SDK и эмулятор Windows Phone 7 “не cработали” (это цитата) на его компьютере т.к. им не понравился видеоадаптер или настройки графического процессора. А вот приложения разработанные с использованием FireMokey, продолжает Всеволод, совершенно не требовательны к аппаратному обеспечению. Давайте посмотрим, как он нам врал. Беспристрастным свидетелем нам будет Process Explorer v15.05 от Марка Русиновича. Итак, качаем приложение Евгения и запускаем (скриншотов приложения Евгения не привожу, они есть по ссылке на его работу. Обратите внимание на размытость шрифтов).

Запустили приложение. Смотрим на потребление:

afterstart_memory 

Нескромно, но можно простить “передовой технологии”. Переходим к разделу “Уроки” и выбираем “Урок 5”. Начинается подготовка сцены. Процесс этот длительный (у меня заняло чуть больше минуты, на четырехядерном Phenom II с частотой 3.3GHz), запаситесь терпением. Сцена построена. Смотрим на потребление:

opened_lesson

Обезьяна хорошо подкрепилась. Даже очень хорошо. Теперь попробуйте подвигать мышку над кнопками вариантов ответов. Ощущение, что GUI реагирует ну о-о-очень вяло, не так-ли? Смотрите на график использования CPU (я имею ввиду, что вы должны сами это попробовать, на своем компьютере) – в эти моменты его загрузка приближается к 100% (у меня было ~21.5% для четырехядерного процессора, что эквивалетно 86% для одноядерного). А ведь нам кто-то рассказывал про GPU accelerated graphics. Ладно, идем дальше. Отвечаем на все вопросы урока. Смотрим потребление:

after_lesson

Глаза не округлились? Теперь посмотрите, для сравнения, сколько потребляет 3D-стрелялка FarCry с активным игровым процессом (уровень называется Фабрика, если кому, вдруг, интересно) запущенная в полноэкранном режиме 1440x900:

farcry 

Выводы делайте сами.

четверг, июля 05, 2012

Delphi XE2 Update 4 HotFix 1. А с дженериками до сих пор проблемы :(

Хотите получить Access Violation на абсолютно ровном месте, без намека на ухабы? Велком, как говорится:

program array_of_generic_record;

{$APPTYPE CONSOLE}

Uses

TypInfo;

Type

TRec<T> = Record
  FField : T;
End;

Var

a : Array Of TRec<TObject>;
i : Integer;
r : TRec<TObject>;

begin

WriteLn(SizeOf(TRec<TObject>)); // 4
WriteLn(GetTypeData(TypeInfo(TRec<TObject>))^.elSize); // 4

SetLength(A, 1000000); // but system.DynArraySetLength.elSize = 1; line 28288
                        // (DelphiXE2 update 4 hotfix 1); look at attached screenshot: bug.png

// absolutely normal code lead to access violation error
For i := Low(a) To High(a) Do
  a[i] := r;

end.

 

В общем, из описания понятно, что в системном модуле неверно получается размер элемента динамического массива. Из-за чего, понятное дело, памяти выделяется меньше и попытки работать с таким массивом приводят к краху. На дворе 2012 год. Блин, когда они уже нормальный компилятор осилят написать. Лучи ненависти вам, абракадабры :E

 

p.s. QC #106917

среда, апреля 18, 2012

Firemonkey. Анимммммация.

Полюбуйтесь:

fmx_animmmmmation

Параметры анимации:

  • Продолжительность 0.5 сек
  • Стартовое значение 6
  • Конечное значение 64

В уголочке приложение работающее под виртуальной машиной с Windows XP и приложение работающее на хост-машине с Windows 7. Приложение пишет в Memo-лог изменения свойства Step на которое настроена анимация.

Обнаруженных косяков два:

  1. Дважды приходит стартовое значение
  2. Разное количество “шагов” анимации при идентичных параметрах

А я думаю чего это у меня анимашка так дергается на семерке, и отчего кажется более плавной на виртуализированной XP. Ужас, блин.

понедельник, декабря 05, 2011

Знатные грабельки компилятора

Сегодня налетел на такое:

program nested_exception_class;

{$APPTYPE CONSOLE}

{$R *.res}

uses
SysUtils;

Type

EUnitException = Class(Exception);

//
TMyRec = Record

Type

Exception = Class(EUnitException);

EOtherException = Class(Exception);

End;
//

begin

// ожидается: TMyRec.Exception, в действительности: Exception
WriteLn(TMyRec.EOtherException.ClassParent.ClassName);

// утверждение должно быть истинным, но нарушается
Assert(TMyRec.EOtherException.ClassParent = TMyRec.Exception);

end.


Компилятор выбрал неправильного родителя для моего класса (EOtherException), хотя в редакторе, если кликнуть (Ctrl+Click) по, родителю (Class(Exception)) переход происходит к “правильному” классу (TMyRec.Exception). Баг воспроизводится в Delphi 2006, Delphi XE2 Update 2, промежуточные не проверял, но думаю и там воспроизведется.

среда, декабря 01, 2010

Вы все еще верите докам?

Вот что говорит Platform SDK о реализации метода Invoke, в части о возвращаемых значениях, интерфейса IDispatch:

DISP_E_NONAMEDARGS

This implementation of IDispatch does not support named arguments.

А вот что говорит система получив DISP_E_NONAMEDARGS:

Eng:

---------------------------
test
---------------------------
No named arguments.
---------------------------
OK  
---------------------------

Rus:

---------------------------
test
---------------------------
Именованные аргументы отсутствуют.
---------------------------
ОК  
---------------------------

 

Совсем одно и то же, правда?

четверг, ноября 25, 2010

Условная компиляция: defines vs. const

Те кому приходится обеспечивать работоспособность кода на нескольких версиях Delphi не по наслышке знают о “прелестях” условной компиляции. Довольно сложно держать в голове набор фич каждой версии и особенности их работы. Ориентация на CompilerVersion, RTLVersion и VERXXX кажется простым делом в момент написания кода, но превращается в кошмар к моменту его рефакторинга т.к. все детали из головы уже выветрились и скучные выражения вроде {$IF CompilerVersion >= 18.5} ясности не добавляют. Обычно эта проблема решается с помощью включаемых файлов (те, что с расширением .inc), где, основываясь на значениях перечисленных выше сущностей (и возможно некоторых других), создается некий набор определений (defines) с читаемыми именами. Делается это, например, так:

{$IFNDEF FPC}
{$DEFINE DCC}
{$ENDIF}
...
// Anonymous methods
{$IF Defined(DCC) and (CompilerVersion >= 20)}
{$DEFINE HAS_ANON_METHODS}
{$IFEND}


Тут мы видим создаваемое определение HAS_ANON_METHODS, которое в дальнейшем позволит нам не вспоминать о версии компилятора, а просто и удобно писать код:



Type
TMyEvent = {$IFDEF HAS_ANON_METHODS}Reference To {$ENDIF}Procedure(Sender : TObject) Of Object;


Но так ли, на самом деле, это удобно? Судите сами. CodeInsight не обеспечивает подсказки для определений. Написав “HAS_” и нажав Ctrl+Space вы не получите весь список возможных определений, а значит снова должны все держать в голове. Это не удобно. Лично меня это просто убивало. Однако, решение есть (для версий Delphi начиная с 2005):



Unit Common.Features;

Interface

Type

//
Delphi = Record

Type

//
Platform = Record

Const

Windows = {$IF Defined(MSWINDOWS)}True{$ELSE}False{$IFEND};
Linux = {$IF Defined(LNUX)}True{$ELSE}False{$IFEND};
MacOS = {$IF Defined(MACOS)}True{$ELSE}False{$IFEND};

{$REGION ' Platform check '}

{$IF Ord(Windows) + Ord(Linux) + Ord(MacOS) <> 1}

{$MESSAGE FATAL 'Unknown platform'}

{$IFEND}

{$ENDREGION}

x32 = SizeOf(Pointer) = 4;
x64 = SizeOf(Pointer) = 8;

End;
//

//
Language = Record

Const

Unicode = {$IF Declared(UnicodeString)}True{$ELSE}False{$IFEND};
Generics = CompilerVersion > 18.5;
AnonymousMethods = CompilerVersion >= 20;
Attributes = {$IF Declared(TCustomAttribute)}True{$ELSE}False{$IFEND};

End;
//

//
RTL = Record

Type

//
TObject = Record

Const

ToString = RTLVersion >= 20;

End;
//

//
ObjectInvoke = Record

Const

MaxParams = {$IF RTLVersion < 20}10{$ELSE}32{$IFEND};

End;
//

End;
//

End;
//

Implementation

End.


Это не законченное решение, пока это только концепт. Надеюсь, основная идея понятна. Небольшой пример кода:



scode      := E_FAIL;
bstrSource := {$IF Not Delphi.Language.Unicode}UniUtf8Decode{$IFEND}(ClassName);

{$IF Delphi.RTL.TObject.ToString}

bstrDescription := ExceptObject.ToString

{$ELSE}

If ExceptObject Is Exception Then
bstrDescription := Exception(ExceptObject).Message
Else
bstrDescription := {$IF Not Delphi.Language.Unicode}UniUtf8Decode{$IFEND}(ExceptObject.ClassName);

{$IFEND}


 



Помимо того, что тут мы сразу видим иерархию (и это очень помогает), нам еще и CodeInsight будет помогать (только за пределами фигурных скобок).



26.11.2010



Забыл написать о самом серьезном преимуществе такого решения. Компилятор контролирует корректность идентификаторов (правда с некоторыми оговорками, но это не важно), и если где-то ошибиться в написании то такой код просто не скомпилируется.

суббота, июня 26, 2010

Generics vs. Inline

Директива Inline не действует на методы в дженериках. Кажется, благое дело обернуть работу с динамическими массивами структурой-дженериком дабы увеличить функциональность путем добавления простых методов Add, Remove, Insert и т.п. Но все благие намерения натыкаются на суровую реальность в которой существует компилятор Delphi :( Столкновение произошло на этапе добавления свойства Items с сеттером SetItem и геттером GetItem, которые, конечно-же, были объявлены как Inline ведь их тела состоят ровно из одной строки (делать проверки индексов в столь тонкой обертке не практично и даже вредно), а вызываться они могут очень и очень часто. После проверки выяснилось, что компилятор не разворачивает тела этих методов, а делает их вызовы :( Можно, конечно, было объявить свойство без сеттера и геттера, но такие свойства не могут быть дефолтными, а значит писать код вида arr[index] := x; уже не удастся.

“Что-же так все неуклюже-то?” © Особенности национальной охоты.

понедельник, января 25, 2010

Ужасы… Windows Platform SDK

Пользовался Windows Platform SDK for Windows Vista.  Желая иметь самую свежую документацию скачал новый Windows SDK for Windows 7 and .NET Framework 3.5 Service Pack 1 (Build date: 6/11/2009).  Ужас. Смотрим статью о WideCharToMultiByte:

Список кодовых страниц для которых флаги и некоторые параметры должны быть нулевыми.

Список из нового SDK:

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 57002 through 57011
  • 65000 (UTF-7)
  • 42 (Symbol)

А вот страницы из прежнего SDK:

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 52936
  • 54936
  • 57002 through 57011
  • 65000 (UTF7)
  • 42 (Symbol)

 

Как видим, из нового SDK исчезло упоминание страницы 52936 (54936 упоминается в документации дополнительно). Здравствуйте, грабли!

Теперь сравните описания параметров.

Новый SDK:

lpDefaultChar [in]

Optional. Pointer to the character to use if a character cannot be represented in the specified code page. The application sets this parameter to NULL if the function is to use a system default value. To obtain the system default character, the application can call the GetCPInfo or GetCPInfoEx function.

For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

lpUsedDefaultChar [out]

Optional. Pointer to a flag that indicates if the function has used a default character in the conversion. The flag is set to TRUE if one or more characters in the source string cannot be represented in the specified code page. Otherwise, the flag is set to FALSE. This parameter can be set to NULL.

For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

И прежний SDK:

lpDefaultChar

[in] Pointer to the character to use if a wide character cannot be represented in the specified code page. The application sets this parameter to a null pointer if the function is to use a system default value. To obtain the system default character, the application can call the GetCPInfo or GetCPInfoEx function.

For the code pages listed for dwFlags, this parameter must be set to a null pointer. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

lpUsedDefaultChar
[in] Pointer to a flag that indicates if the function is to use a default character in the conversion. The flag is set to TRUE if a default character is necessary, and to FALSE otherwise. This parameter can be set to a null pointer.

For the code pages mentioned in dwFlags, lpUsedDefaultChar must be a null pointer. Otherwise, the function fails with ERROR_INVALID_PARAMETER.

Нужно ли говорить, что информация в новом SDK не соответствует действительности. Здравствуйте, еще одни грабли! Ужас… Как можно верить такой доке? Остается только проверять.

суббота, октября 31, 2009

Delphi 2010. Быдлокод

Юнит DBXJSON.pas. Я вообще в ауте...

class function TJSONString.Hex(const Digit: Integer): Byte;
var
HexData: TBytes;
begin
SetLength(HexData,16);
HexData[0] := Ord('0');
HexData[1] := Ord('1');
HexData[2] := Ord('2');
HexData[3] := Ord('3');
HexData[4] := Ord('4');
HexData[5] := Ord('5');
HexData[6] := Ord('6');
HexData[7] := Ord('7');
HexData[8] := Ord('8');
HexData[9] := Ord('9');
HexData[10] := Ord('A');
HexData[11] := Ord('B');
HexData[12] := Ord('C');
HexData[13] := Ord('D');
HexData[14] := Ord('E');
HexData[15] := Ord('F');
Result := HexData[Digit];
end;

вторник, октября 20, 2009

Delphi 2010. System.TObject.GetInterface

Полюбуйтесь на код обеспечивающий проверку идентификатора интерфейса на соответствие "magic GUID" ({CEDF24DE-80A4-447D-8C75-EB871DC121FD}), для безопасного кастинга (TMyObject(TMyIntf)) к объектому типу:

if (Int64(ObjCastGUID.D1) = Int64(IID.D1)) and
(Int64(ObjCastGUID.D4) = Int64(IID.D4)) then
Pointer(Obj) := Self;

И это в системном юните... #78808

вторник, мая 26, 2009

Ubuntu 9.04

Четыре дня назад получил по почте новую версию Ubuntu. Итог: оно все лучше и лучше. Несмотря на то, что чего-то не срослось с wubi общие впечатления самые положительные. Очень порадовала, сразу бросившаяся в глаза, качественная настройка саб-пиксельного сглаживания шрифтов. Им бы еще иконки отдизайнить в какой-нибудь конторе, чтоб в едином стиле, да в Гноме немного уменьшить контролы. В общем, мне понравилось :)

воскресенье, мая 17, 2009

#72213 Fixed

На фикс такой очевидной ошибки компилятора потребовалось два месяца... Страшно подумать сколько будут фиксить некорректную инициализацию/финализацию advanced-records, на которую налететь не так просто :( Вот и юзай новые языковые фичи...

вторник, апреля 28, 2009

Три класса секундомеров

Выложен модуль Common.Classes.pas содержащий три класса (advanced-records) секундомеров. TLowResStopwatch на основе GetTickCount, THighResStopwatch на основе QueryPerformanceCounter, и TStopwatch использующий один из предыдущих классов секундомеров в зависимости от аппаратной части компьютера.

вторник, апреля 21, 2009

Исправление в Interface Extender

Исправлена ошибка при работе с динамическим массивом. Проявлялась при попытке добавить несколько интерфейсов на один класс.

понедельник, апреля 20, 2009

Расширенная поддержка интерфейсов для Delphi

В блоге Алексея Тимохина озвучена хотелка касающаяся поддержки интерфейсов базовыми классами. На мой взгляд, идея весьма спорная, во всяком случае при нынешнем положении дел в языке. Однако, реализовать нечно подобное можно уже сейчас ;) Тут я набросал пример, как это может быть реализовано (intfExtender.pas реализует непосредственно механизм расширения, а unit1.pas содержит два примера). Если кому пригодится, буду только рад ;) Универсальность прикладного кода, о которой говорит Алексей, таким образом можно обеспечить.

p.s. Модуль сильно не тестировался, посему никаких гарантий если что ;)

среда, апреля 15, 2009

Очередные ошибки инициализации/финализации в Delphi 2006 - 2009

Отчет #73008 описывает несвоевременную финализцию энумератора являющегося интерфейсом при использовании в основном теле программы (в процедурах и функциях работает нормально), что в некоторых случаях может приводить к ошибкам доступа (Access violation).

Отчет #73009 описывает неадекватную инициализацию (а точнее ее отсутствие) интерфейсного поля advanced record в случае, когда последняя используется в качестве возвращаемого значения.

пятница, апреля 10, 2009

Утечки и неадекватное поведение Delphi 2006 - 2009 Update 1

При передаче advanced record имеющей интерфейсное поле, в качестве константного параметра, есть немалый шанс налететь на утечку и получить неадекватное поведение т.к. даже константный параметр имеющий размер поинтера передается по значению. Подробности и код в отчете #72878

понедельник, марта 23, 2009

суббота, марта 14, 2009

Ошибка компиляции на ровном месте

Если у класса или записи определить вложенный энумератор, который будет иметь поля "управляемых" типов (string, interface, dynamic array, variant), то при попытке использования в операторе for-in-do мы получим ошибку компиляции на несоответствие типов. Воспроизводится, и на Turbo Delphi Explorer, и на Delphi 2009 Update 1. Репорт #72213.

понедельник, февраля 02, 2009

Обновлен Common.Encodings.pas

На домашней страничке выложен обновленный Common.Encodings.pas

Добавлены классы кодировок UTF-32 и UTF-32BE (только Delphi 2009), добавлен метод определения кодировки по BOM. Добавлены функции-аналоги WideCharToMultiByte и MultiByteToWideChar для кодировок UTF-16, UTF-16BE, UTF-32, UTF-32BE. Функции приведены к единым сигнатурам. Определен процедурный тип с сигнатурой кодирующей и декодирующей функций. Добавлен воркараунд для корректного определения доступности кодировок UTF-7, UTF-8 под Windows NT 4.0

суббота, января 31, 2009

Утечки на интерфейсных параметрах

Теряются объекты передаваемые в качестве параметров интерфейсных типов в случае, когда не происходит кастинга с проверкой (as) к определенному интерфейсу. Для кода:

 Test(TMyObject.Create('1')); // will not be destroyed
Test(IInterface(TMyObject.Create('2'))); // will not be destroyed
Test(TMyObject.Create('3') As IInterface);

утечки будут в первых двух вызовах. Воспроизводится, и на Turbo Delphi, и на Delphi 2009. Отчет #71015.

пятница, января 16, 2009

QC, в чем магия?

Только вчера "ругался" на неторопливость правки багов в компиляторе, а сегодня глянул на свой  отчет №70529 и удивился -- он получил статус Internally Opened (как я понимаю, над ошибкой уже работают). Так вот, в чем магия? Неужели голос Алексея был решающим? ;)

четверг, января 15, 2009

Ошибка в Delphi 2009 Update 1

Передача односимвольной строки в диспетчеризируемый метод приводит к передаче кода символа, а не строки. Лечится приведением строки к строке :) т.е. вот так: String('1'). Репорт номер 70529, поддержите, кому не лень.

пятница, октября 31, 2008

Приемчик

Потребовалось символ юникод строки проверить на предмет вхождения в суррогатную пару (а конкретно, является ли символ младшим суррогатом). Все бы ничего, но индекс символа вычисляемый и вычислять его для каждого сравнения (коих собственно два) не кошерно. Есть варианты решения:

1. Сохранить индекс в переменной. Просто, но нужна переменная.

2. Сделать функцию и заинлайнить ее. Нужна функция.

3. Извернуться.

Собственно, я о третьем варианте:

     With WordRec(AContent[ACharIndex + CharCount]) Do
If (Word(Bytes) >= $DC00) And (Word(Bytes) <= $DFFF) Then;

воскресенье, октября 26, 2008

Оперативность QC

Все шесть моих репортов прошли во внутреннюю базу в среднем через 2 недели после подачи. Шустро. Правда с одним лажа вышла, отрепортил о баге пофикшеном в релизе :(

пятница, октября 10, 2008

Полный QCец...

Только я отрепортил о нескольких ошибках, как меня снова перестало пускать к сервису... Плавающие баги, они самые милые, ага :)

p.s.

Ой блин... Снял галку DN Authentification и все снова заработало. Сплошные воркараунды :))

среда, октября 08, 2008

понедельник, октября 06, 2008

Val в Delphi 2009

Знаете как работает Val с юникодом? Рассматриваются лишь младшие байты символов :( Для проверки прогоните цикл от lo(Char) до high(Char) и посмотрите, сколько символов будет "успешно" преобразовано в число. Грустно. Если кто-то это читает, заQCите плиз...

пятница, октября 03, 2008

Обновился Common.Encodings

В метод GetEncoding добавлен параметр со значением по умолчанию позволяющий указывать на возможность использования стандартных (определенных в классе TEncoding) кодировок. Скажем, код GetEncoding('utf-16') создаст новый объект класса TUnicodeEncoding, а код GetEncoding('utf-16', True) вернет существующий объект TEncoding.Unicode;

среда, сентября 24, 2008

Delphi 2009 aka Tiburon. TEncoding.

На домашней страничке выложен модуль Common.Encodings расширяющий возможности стандартного класса TEncoding. Модуль содержит class helper для TEncoding и несколько вспомогательных advanced records.

Примеры использования: 

1.) Перечисление доступных кодировок

Var

ei : TEncodingInfo;

Begin

For ei In TEncoding.Encodings Do
If ei.IsAvailable Then
WriteLn('codepage: ', ei.CodePage, ' name: ', ei.Name);

End;

2.) Создание кодировки по имени:

 TEncoding.Encodings.ByName('utf-16').GetEncoding;

или

 TEncoding.GetEncoding('utf-16');

3.) Создание кодировки по номеру кодовой страницы:

 TEncoding.Encodings.ByCodePage(CP_UTF16_BE).GetEncoding;

или

 TEncoding.GetEncoding(CP_UTF16_BE);

4.) Получение информации о существющей кодировке:

 With TEncoding.UTF8.GetInfo Do
WriteLn('codepage: ', CodePage, ' name: ', Name, ' display name: ', DisplayName);

пятница, сентября 19, 2008

Delphi 2009. Вкратце.

Юникод+дженерики+анонимные методы это все понятно.

Порадовала скорость среды! И особенно скорость CodeInsight (несмотря на то, что я его все равно всегда отключаю)

Наконец-то они научились различать Implicit и Explicit для записей в нативе (2007 не пробовал, может и там уже было). Но вот редактор сильно подкачал, разучившись (в 2006 он и не сильно-то умел) перемещаться по Ctrl+Shift+Up/Down между декларацией и реализацией перегруженных операторов записи (правда, я тестировал на 12.0.3155.16733, может в релизе и поправили), а также разучился (для перегруженных операторов опять же) по Ctrl+Shift+C создавать макет метода по описанию.

Появился UInt64 -- беззнаковое 64битное число.

BeginThread и TInterfaceList по-прежнему имеют потенциальные утечки.

Неработает передача Int64 в параметре диспетчеризуемого метода (вызов метода от вариантной переменной). Точнее, если передавать переменную типа Int64 все работает, а если значение Int64(1024) -- нет.

Exception обзавелся потенциальной поддержкой стек-трейсинга, но только потенциальной :)

Очень порадовал {$POINTERMATH}

В комментариях исходников встречается sysmac.h. Интересно, это то о чем я думаю...?

Порадовал хелпер для TRTLCriticalSection (syncobjs.pas)

Порадовал обновленный ZLib

Огорчает нелепость использования системных InterlockedCompareExchangePointer (и прочих Interlocked...) при наличии нативных в system.pas

Ribbon огорчил неаккуратными скинами (ждем редактора :) или сторонних, качественных скинов) и моргающей отрисовкой. DoubleBuffered Ribbon-контрола  не помогает, а буферизовать форму то еще извращение.

TLinkLabel неюзабельна совершенно, т.к. на системах младше XP, линки распознаваться не будут и пользователь будет видеть разметку.

понедельник, мая 12, 2008

Embarcadero + CodeGear

О покупке CodeGear компанией Embarcadero, стало известно почти неделю тому назад. А вот обращение к клиентам CodeGear, в котором, в частности, говорится о том, что дальнейшая разработка будет нацелена на гетерогенные платформы и различные СУБД. Ребята, идем на Linux и MacOS? :)

четверг, апреля 24, 2008

XML-RPC: Общие ошибки

Одна из самых часто встречающихся ошибок в реализациях XML-RPC -- экранирование лишних символов в строках. Лишних в том смысле, что спецификация XML-RPC их экранирования не требует. Для корректного парсинга пакета требуется экранировать символы: < (&lt;) и & (&amp;). Любые другие символы экранироваться не должны, но очень часто ошибочно экранируют еще и другие символы: ' (&apos;), " (&quot;), > (&gt;).

среда, апреля 23, 2008

Extended RTTI {$METHODINFO ON}

Пару дней назад, налетел на очень интересную граблю. В своем XML-RPC сервере я использую возможность Delphi создавать расширенную RTTI, для регистрации объектов на сервере. Описывается класс с некоторым API, публичная часть (та, что будет доступна XML-RPC клиентам) выносится в секцию Published (для которой и создается Extended RTTI). Затем создается объект данного класса  и регистрируется на сервере. В процессе регистрации сервер получает прототипы методов разбирая RTTI. Все работает прекрасно, кроме того, что помимо методов вынесенных в Published, компилятор создает RTTI еще и для некоторых (даже перегруженных!) методов из секции Public. Грабля, вылезла на довольно сложном классе имеющем nested types. На простых классах такого не обнаруживается.

пятница, апреля 18, 2008

Утечка в TInterfaceList

У данного списка (как впрочем и у TList, и его потомков) есть свойство Count позволяющее, как определять количество элементов списка, так и устанавливать его. Очень удобно использовать возможность назначения количества элементов, для многократной очистки списка (т.к. делается это без перераспределения памяти к которому приводит стандартный Clear). Однако, в классе TInterfaceList данная операция приводит к потере ссылок на хранящиеся интерфейсы, следовательно они никогда не будут освобождены.

воскресенье, апреля 13, 2008

XML-RPC. Снова :)

Сегодня получил 5046 вызовов в секунду (и это на отладочной версии, со всеми проверками и ассертами)!

вторник, апреля 08, 2008

Delphi хотелка

Уже который раз ловлю себя на мысли, что очень хочется иметь параметризованные циклы for-in-do. Тогда можно было бы писать примерно так: For Item[Param] In Items Do... Что приводило бы к выборке значений соответствующих параметрам (разумеется, при поддержке перечислителя).

И вторая хотелка касающаяся for-in-do это наличие двух методов вызываемых перед началом перечисления и после. Что помогло бы при реализации перечислителей в виде advanced records, когда им (перечислителям) требуется выполнять некоторые операции (например блокировка/разблокировка) над контейнером.

воскресенье, марта 30, 2008

А знаете ли вы, что...

Операция сравнения AString = '' выполняется в два раза быстрее чем Length(AString) = 0 для AnsiString, и медленнее (примерно в 1.3) для WideString при условии, что строка не пустая.

Плагиат

Какой то пельмень, по имени Max, тырит посты из моего блога (и видимо не только из моего) и публикует на своем (ссылку не дам, ибо нефиг)  от своего имени... Этот пост для него.

четверг, марта 20, 2008

Новые высоты :)

Сегодня, после небольшой переделки работы с SAX'ом, получил скорость в 4096 (число-то какое :)) вызовов XML-RPC в секунду (метод без параметров, возвращающий nil)

воскресенье, января 27, 2008

HTML Display Components

Кажется, сабжевая библиотека тихо умирает :( Автор отказывается делать какие-либо изменения/дополнения в будущем.

пятница, января 11, 2008

Ужос, нах...

Вчера, на одном форуме, увидел вопрос дельфиста:

"Раньше использовал инди смтп а как его запихать в поток не знаю. Формы же нет, куда его перетащить можно."

Это было бы смешно, если б не было так грустно :( Остается надеяться, что вот такие кадры, в скором времени, свалят под .Net (а именно такие, в основном, и валят, т.к. Delphi их донимает "акцесс виолатион'ами") и перестанут порочить доброе имя Дельфистов. В результате, свалившие будут писать тормозных и охотчих до памяти монстров (но главное (!), без "акцесс виолатион'ов" :D) на, и без того, тормозящей платформе, а лагерь .Net получит перебежавших чайников, в добавок к родным образованиям :) и постепенно будет ими опорочен :). Аминь.

пятница, января 04, 2008

Очередная бага TAlXmlDocument

Ошибка, иногда, появляется при парсинге документов имеющих комментарии. Воспроизвести ошибку довольно просто -- в цикле создавать и парсить документ, с комментарием переменной длинны, от одного символа до размера буфера. Дело в том, что в процедуре PosInXmlString не учитываются некоторые особенности при расчете смещения. Однако, решить проблему очень просто:

  1. В процедуре PosInXmlString изменить строку Offset := RawXmlStringLength - RawXmlStringPos{ + 2};
  2. В процедуре AnalyzeComment добавить условие на размер комментария, длина которого не может быть меньше нуля And (P1 - RawXmlStringPos - 4 >= 0)

четверг, декабря 27, 2007

Проблема скорости TALXmlDocument

В общем, прилетело откуда не ждали :( Пару дней назад решил попробовать отдачу статистики работы сервера XML-RPC в комментарие пакета (т.е. вместо, собственно, комментария отдается XML документ c различными данными). Все бы ничего, да только производительность сервера просела очень значительно... На два порядка, т.е. в 100 с лишним раз. Первым подозреваемым стал именно парсер т.к. непонятки с размером буфера у него уже были. Написал автору -- тишина. Решил сам покопаться в дебрях чужих исходников :). Профайлера нема -- ищем проблему читая код :) Нужно отдать автору парсера должное, он многое сделал для того, чтоб его создание, по скоростным характеристикам, укладывало на лопатки конкурентов :) Там и ассемблерный код, и адаптирующийся под процессор набор процедур/функций для работы со строками. В общем видно, что человек старался. Однако нашел я там и такой код, что просто волосы дыбом и нужного смайла не могу найти. Код приводить не стану т.к. вне контекста (читай метода использования) он абсолютно нормален, скажу лишь, что функция называется CharPosInString. После того, как я ее переписал тормоза сократились в четыре раза (т.е. стало тормозить не в 100 раз, а в 25 :)). Ищу проблему дальше. Меняю размер комментария и вижу, что чем больше комментарий, тем сильнее тормоза. Потом убираю комментарий и добавляю в пакет параметр типа Base64 размером в 64Kb -- снова тормоза. Начинаю грешить на внутренний буфер парсера. После некоторых манипуляций выясняется, что какой бы ни была константа BufferSize, парсер выделяет буфер под самый большой контент встретившийся ему при разборе и потом спокойно работает с этим буфером. Нашел функцию ExpandRawXmlString отвечающую за увеличение буфера при необходимости. В одно из условий добавил несколько строчек и проблема разрешилась (т.е. буффер увеличвается только на время, когда он нужен, а затем возвращается к прежним размерам). В общем и целом, тормоза пропали совсем, но сердцем чую -- нужен профайлер, чтоб найти корень зла тормозящий на любом буфере больше 64 байт :).

суббота, декабря 01, 2007

Странный ping. Yandex XML-RPC

Сегодня, от нечего делать, xml-rpc debugger'ом решил дернуть (а вдруг работает) метод system.getCapabilities у сервера Яндекса, который обрабатывает пинги блогов. В ответ меня поблагодарили за пинг и сообщили, что все прошло без ошибок :) Прикольно они там реализовали xml-rpc...

понедельник, ноября 19, 2007

Что-то, как-то...

Ну, совсем меня Ubuntu убила...  Вчерась решил заархивировать папку Install весом в 9Gb находящуюся на виндовом ntfs разделе. Не скажу, что в этом была большая необходимость, т.к. архив я предварительно сделал под Windows, просто хотелось посмотреть, как оно в Ubuntu :) Открываю контестное меню на папке Install, выбираю пункт Add to archive (или что-то вроде этого, точно не помню), выбираю тип архива tar.gzip. Отлично! Пошел процесс архивирования. Минут через пять, я решаю прервать это дело. Но не тут-то было... Окошечко, конечно закрылось, но вот индикатор диска продолжал указывать на сильную активность. Подождав еще минут пять, я запустил системный монитор и был несколько удивлен увиденным... В списке процессов преспокойненько болтался процесс tar и явно продолжал архивацию. Я в шоке.

суббота, ноября 17, 2007

Вторые впечатления...

Ох, неоднозначные... Все, вроде, в Ubuntu приятно, но вот словил таки две аномалии. Аномалия первая. Запустил поиск файлов по маске *.png. Файлов нашлось аж 16 тысяч с копейками. Затем, эти найденные файлы, перетаскиваю (drag&drop) в соседнее окошечно с открытой папкой. Все, ОС померла, в смысле впала в состояние анабиоза, в котором только дисковая система продолжала свою активность. Сразу зачах плейер (не помню название, но это тот, из поставки, что с подкастами), перестал двигаться курсор мышки. В общем через некоторое, весьма продолжительное, время диалог поиска файлов самопроизвольно закрылся безо всяких сообщений (так ничего и не скопировалось). Аномалия вторая. Слушая музычку через упомянутый уже плейер, я решил еще помсотреть видео из папки Examples. Запускаю на просмотр видео с Нельсоном Манделлой, и... Это все. Запускается другой плейер и ОС зависает намертво (плейер с подкастами перестает играть). Судя по тому, как зашуршал кулер на проце, чем то ОС его грузила, но прождав минут 10 и не получив ни какого результата я просто выключил буку. Вот такие дела.

среда, ноября 14, 2007

Первые впечатления

Попробовав Ubuntu с LiveCD, я остался очень приятно удивлен качеством дистрибьютива. Имея прежний опыт общения лишь с ASP-Linux (кажется 9.0), могу сказать, что Ubuntu это уже не просто шаг на десктопы пользователей, это полноценный (ну пусть, с некоторыми оговорками) конкурент Windows! Поразила отзывчивость интерфейса при сворачивании/восстановлении окон в момент пиковой загрузки процессора. Кстати, все оборудование моего ноутбука (Toshiba Satellite Pro M30) было определено корректно, и даже noname блютуз донгл определился и заработал. Единственная претензия, так это устойчивое желание Ubuntu ползти в инет, что за драйвером для видюхи (чтоб работали эффекты Compiz Fuzion), что за русским языком для локализации (посмотреть на русский фейс было просто интересно). Возможно, это из-за того, что я использовал LiveCD, а не устанавливал систему на винт. Очень порадовало качество сглаживания шрифтов Subpixel Smoothing, кажется более качественным нежели Windows ClearType. А вот сами шрифты изяществом не блещут. В общем и целом, Ubuntu зачет!

Убунта

Сегодня получил заказанные 09.10 диски Ubuntu! Доставили прямо в почтовый ящик. Теперь буду смотреть :)

среда, ноября 07, 2007

XML-RPC boxcarring 2

Позавчерашний результат в 4500 вызовов в секунду, что-то не очень меня порадовал... По моим прикидкам, должно было работать значительно быстрее. Сегодня начал искать узкое место. Им оказался используемый мною SAX парсер, который сильно тормозил при размере пакета в 2 мегабайта. Порылся в его исходниках (благо, он открытый и бесплатный), и попытался без профилирования определить, где могут быть затыки. Нашел константу BufferSize = 8192 байта. Отлично, подумал я :), сейчас увеличу буфер в два раза и посмотрю. Посмотрел :( Скорость упала вдвое. Я в полнейшем шоке. Решил буфер уменьшить... Скорость возросла :) В общем, я дошел до буфера в 16 байт :) Причем с таким буфером, скорость хорошая, и при парсинге больших строк, и при парсинге файловых стримов (85Мб).

P.S. Руки дойдут, посмотрю на него под профайлером, а пока результат меня удовлетворил -- 16667 вызовов в секунду!

понедельник, ноября 05, 2007

пятница, ноября 02, 2007

Delphi-грабельки 2

Ох уж эти грабельки... Сегодня наступил там, где  и не ожидалось :( Есть в ObjectPascal чудесная функция Slice, которая возвращает N первых элементов открытого массива и использовать которую можно только, как параметр процедуры или функции. Вот сегодня мне эта радость и понадобилась. Надобность обернулась руганью компилятора о том, что функция используется не по назначению т.е. не в качестве параметра функции или процедуры. Ну, это компилятор так думал... На самом деле, все оказалось проще. Функция, а точнее метод, в который я собирался передать кусочек массива, являлся перегруженным и имел сестру-процедуру принимавшую два параметра, первым из которых должен был быть открытый массив  (который, собственно, Slice и возвращает). Такие вот грабельки. Пришлось морщить лоб и выдумывать другое имя для сестры-процедуры :(

среда, октября 31, 2007

Delphi-грабельки

Оказывается, в Delphi нельзя объявить больше одного перегруженного метода в секции Published.

Сегодня я на эти грабельки наступил... Обидно :(

пятница, октября 19, 2007

Набросок XML-RPC сервера

Сегодня сделал таки набросок XML-RPC сервера чтоб оценить скорость работы. В общем скорость получилась потрясающая: 3750 вызовов в секунду! Правда ввиду того, что это лишь набросок, где отсутствует куча проверок, в окончательном варианте цифра будет поменьше. Но думается мне, что не меньше 3500 :)

вторник, октября 16, 2007

XML-RPC хотелка

Очень хочется официального апдейта спецификации XML-RPC с целью добавления 64-битных целых. Не очень радует перспектива передавать такие числа в виде строки/двуэлементного массива/записи с двумя членами. Куда бы написать об этом (?), xmlrpc.com совсем мертв, кажется :(

среда, октября 10, 2007

Семь нянек

Сегодня бегло полистал вот эту книгу:

Programming Web Services with XML-RPC
Simon St. Laurent
Joe Johnston
Edd Dumbill
Publisher: O'Reilly
First Edition June 2001
ISBN: 0-596-00119-3, 230 pages

Неоднозначные впечатления... Прям на 24 странице,  в пункте 2.3.1.1 Parameters присутствует фраза "Even if the method requires no parameters, the <params> element must still be present." противоречащая спецификации XML-RPC. Вроде и авторов аж трое, а такой косяк допустили. Немного ранее авторы сделали смелый вывод о том, что дубликаты членов структуры запрещены т.к. они (авторы), в противном случае, не могут понять, как может интерпретироваться подобная структура :)

В общем, книга мне не очень понравилась. Какая-то однобокость суждений ощущается.

вторник, октября 09, 2007

Убунта

Сегодня оформил пред-заказ на 2 (32+64 bit) CD Linux Ubuntu 7.10. Интересно, сколько диски будут добираться до меня и действительно ли все будет бесплатно... Решил FPC 2.2 под линуксом посмотреть :)

пятница, сентября 21, 2007

Рекорды скорости

Не то, чтобы я специально подтачивал библиотеку для достижения высоких результатов, просто в следствии совсем крошечной оптимизации удалось получить уже 2583 вызова в секунду :) без модификации серверного компонента.

понедельник, августа 13, 2007

Скорость передачи данных в XML-RPC

Сегодня продолжил тесты на локальной машине. На этот раз решил проверить чистую скорость передачи данных (как если бы передавался файл). В результате, скорость чуть больше 13Мб в секунду! Передавались блоки по 32Кб, в единственном параметре метода, тип Base64 (т.е. реальный блок получался ~43Кб. Не стоит забывать, что спецификация XML-RPC разрешает использовать и строки для передачи бинарных данных). Выходит, что файл размером в 130Мб был бы передан за 10 секунд. Если блоки передавать строкой, а не Base64, скорость получается 28.5Мб в секунду :)

Было желание попробовать этот тест с использованием gzip-сжатия, но мне стало лень прикручивать фильтр к IIS :)

суббота, августа 11, 2007

Скорость XML-RPC

Сегодня протестировал свою библиотеку XML-RPC на локальной машине (до этого тестировал только при нахождении сервера под виртуалкой). Сервер IIS 5.1 под которым работает мой xml-rpc ISAPI. Клиент -- Delphi-приложение. Клиент вызывает метод currentTime.GetCurrentTime возвращающий текущую дату и время. Многократные замеры показывают результат в 2560 вызовов в секунду (и это без использования boxcarring'а и на неспециализированном сервере)!!! Кто там говорил, что XML-RPC не эффективен ;)

воскресенье, августа 05, 2007

Цвет затемнения в Smoke-screen

Для себя выбрал оптимальный вариант подбора цветов затемнения. Изначально использовал не черный, а очень темно-серый (RGB: 32, 32, 32). Сейчас выбираю цвет в оттенок обоя рабочего стола, т.е. если на обое преобладает зеленый цвет, я немного усиливаю этот цветовой канал (скажем RGB: 32, 48, 16) и ослабляю другой. В результате затемнение ощущается этаким, продолжением обоя :)

четверг, августа 02, 2007

"Турба", ты меня удивляешь...

Сегодня у меня получилось создать объект абстрактного (!) класса... Глюк плавающий и воспроизведению, что-то не поддается.

воскресенье, июля 22, 2007

JSON

Вот тут обнаружил JSON Toolkit v0.3 (с поддержкой RPC). В закладки, однозначно! Пригодится, вдуг решу свой гейт JSON-RPC 2XML-RPC and vice versa сделать :)

среда, июля 18, 2007

Снова баг TurboDelphi/BDS2006

Не помню, может я уже писал об этом, просто позавчера снова напоролся... Имеем свойство интерфейсного типа. Имеем сеттер получающий константный параметр (новое значение св-ва ес-но). Внутри сеттера выполняем проверку поддержки необходимого нам интерфейса средствами Supports(Value, IMyInft); Все. После отработки сеттера, мы теряем интерфейс. Баг обходится либо, отказом от константного параметра либо, проверкой интерфейса расширенной версией Supports с дополнительным параметром. Интересно, в D2007 это воспроизводится?

воскресенье, июня 24, 2007

ControlHooks

На домашней страничке выложены модули (D2006/Turbo ~15Kb)  позволяющие создавать классы-ловушки элементов управления (потомки TControl), а также пример использования (класс-ловушка обеспечивающий принятое в Windows поведение элементов управления Edit и Combobox при статусах Disabled и ReadOnly).

воскресенье, июня 10, 2007

Synapse

В модуле blcksock.pas включена директива {M+}, соответственно все классы библиотеки получают RTTI т.к. имеют published-члены. Не знаю, с какой целью автор это сделал (может для Lazarus'а. Кажется, я что-то слышал об этом), но я, для win32, директиву отключаю.

пятница, июня 01, 2007

Решение с null-stream

Собственно, ничего нового и оригинального я не напишу, но вдруг, кому пригодится :). Есть у меня класс TXmlRpcPacketGenerator, который формирует XML-RPC-пакет в соответствии с параметрами и опциями форматирования (отступы, декларация, варианты компактности). Формирование пакета происходит только в поток т.е. в объект-наследник класса TStream. Встала задача, определения размера будущего пакета ДО его формирования. Было несколько вариантов решения, но остановился я на т.н. null-stream. Создается класс TNullStream(TStream), в котором перекрываются методы Read, Write и Seek. Что делают эти методы понятно из их названия и в контексте названия потока т.е. ничего не делают :), а просто манипулируют счетчиком. Потом в такой поток формируется пакет и задача решена :)

Замечания относительно скорости: самая тяжелая операция в формировании XML-RPC-пакета - кодирование Base64, однако на это можно не обращать внимания т.к. по моим замерам (и моим-же кодером) строка, общим объемом, в 18Mb кодируется всего за 0.25 секунды (PM-1.7Gh 512RAM) (но это время только чистого кодирования). Другая тяжелая операция - это большое количество данных примитивных типов (массивы чисел, дат, булевых и т.п.), однако и это не так страшно, например массив из 100.000 структур формируется за 0.2 секунды и имеет размер 2.4Mb.

вторник, мая 22, 2007

Надоело читать про iso8601

На просторах ненашего интернета читал статьи об XML-RPC. Я, честно говоря, только о русских авторах думал не очень хорошо, а оказалось - эпидемия :) В большинстве (если не во всех) статей авторы пишут, что XML-RPC использует для представления даты и времени стандарт "квази" iso8601 (т.е. это представление, якобы, не соответствует стандарту). Внимательно читая iso8601 я не увидел ни одного несоответствия рекомендациям стандарта. Они, что, друг-друга просто перепечатывают?

вторник, мая 15, 2007

Colocation заблаговременно...

Озадачился найти контору, которая предоставляет услугу colocation за приемлемые (2кило рубля в месяц максимум) деньги и без дурацких ограничений по трафику, вида 1/4 (а у меня задумка такая, что входящего будет больше нежели исходящего). Полазил по инету, полазил, да и опечалился совсем :( У всех ограничения :(( Нашел keyweb.ru, так у них дата-центр в Германии... Что и делать, где железо размещать...???

воскресенье, апреля 22, 2007

Маленький хинт :)

Часто в работе приходится использовать сторонние библиотеки (хотя это можно отнести и к своим) имеющие директивы условной компиляции и соответствующие определения. Это здорово, это позволяет гибко, под нужды приложения, компилировать библиотеку (например я, в UIB включаю UIB_NO_COMPONENT, чтоб предком всех классов стал TObject). Это хорошая практика, но она имеет недостатки: когда происходит обновление версии библиотеки, старые определения (в файлах .inc) могут быть утеряны, не всегда-же все держится в голове. А если таких библиотек несколько? В общем, я для себя нашел способ избавиться от этой головной боли :) В отдельный модуль, или файл проекта (а вообще, куда угодно) подключаются файлы определений (*.inc) библиотек и создаются директивы условной компиляции (пример для UIB):

{$IFDEF DLLREGISTRY}

{$MESSAGE FATAL 'Отключить $DEFINE DLLREGISTRY (jvuib.inc)'}

{$ENDIF}

{$IFNDEF FB20}

{$MESSAGE FATAL 'Включить $DEFINE FB20 (jvuib.inc)'}

{$ENDIF}

{$IFDEF UIBTHREADSAFE}

{$MESSAGE FATAL 'Отключить $DEFINE UIBTHREADSAFE (jvuib.inc)'}

{$ENDIF}

{$IFNDEF UIB_NO_COMPONENT}

{$MESSAGE FATAL 'Включить $DEFINE UIB_NO_COMPONENT (jvuib.inc)'}

{$ENDIF}

Теперь уж точно ничего не забудется при обновлении :)