четверг, декабря 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 вызовов в секунду!

пятница, ноября 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}

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

пятница, марта 16, 2007

OLE automation

Никогда не любил эту штуку. Не, ну здорово, конечно, в Word'е страничку иль в Excel'е табличку/отчетик заделать, но чтоб постоянно использовать - боже упаси. Однако решил, заради эксперимента, прикрутить к своей реализации XML-RPC вызов методов сервера через механизмы диспетчеризации (IDispatch). Надумано - наделано :) Вчера закончил. Результаты, честно говоря, меня очень порадовали. Прямой вызов метода выигрывает у своего диспетчеризуемого аналога всего 0.2 секунды при 10.000 итераций (т.е. разница в пересчете на одну итерацию сопоставима с погрешностью замеров). Проигрывая при  этом, по простоте (правда не сильно) и читабельности кода:

Прямой вызов:
For SIndex := 1 To 50 Do
Memo1.Lines.Add(SysUtils.Format('%d - %s', [SIndex, Call('examples.getStateName', [SIndex])]));

Диспетчеризуемый вызов:
For SIndex := 1 To 50 Do
Memo1.Lines.Add(SysUtils.Format('%d - %s', [SIndex, Server.examples.getStateName(SIndex)]));

пятница, марта 09, 2007

Однако, Linux...

Вчера и сегодня в новостях "Компьютерры" мелькнули сообщения о том, что Dell и HP будут поставлять компьютеры с Linux... Интересное кино.

четверг, февраля 22, 2007

Идеальное хранилище

Вот так высокопарно :) Разумеется, ничего идеального нет, но то, о чем я сегодня пишу, в некотором смысле тянет на это определение ;) Речь пойдет о хранении настроек приложения, как частном случае. Как известно, для хранения настроек изначально (аж со времен DOS) использовались т.н. ini-файлы, текстовые файлы с незамысловатой структурой. Решение очень простое и даже примитивное. Примитивность заключалась в неструктурированности и непизированности хранимых значений, и именно из-за нетипизированности были основные проблемы (конечно, если разработчику не лень в каждом месте выполнять вручную конвертирование типов из строкового представления, для него это не проблема). Потом Майкрософт сказала, что ini-файлы - прошлый век, и всем пора пользоваться реестром (единым системным хранилищем). Там, и типизация, и возможность "структурного" хранения и вообще реестр - rulezzz!  И толпы программистов-леммингов кинулись претворять в жизнь призыв Большого Билла. Но, как оказалось, структурированность реестра не относилась к типизации данных (их по прежнему приходилось хранить в "плоском" виде), структурировать можно было только расположение (что, собственно, присутствовало и в ini-файлах).  Разработчики привыкшие к такому положению дел еще со времен ini-файлов, кажется, не особенно и растроились (запросто храня массивы и структуры в виде бинарных блоков). Но время шло и пользователи стали замечать, что файлы реестра пухнут и, как следствие, система уже не так резва, как после установки. Оказалось, что всему виной приложения оставляющие, даже после своего удаление, в реестре груды мусора. Эта проблема породила целый класс программ-чистильщиков реестра (авторы, наверное, благодарны Большому Биллу). [Кстати, с приходом .Net изменилось отношение Майкрософт к вопросу хранения настроек, теперь они не рекомендуют использовать реестр и снова предлагают хранить все в файлах (все возвращается на круги своя ;))] Потом появилась идея, хранить настройки в файлах формата XML. Идея совсем не плоха, т.к. структурирование заложено в саму суть формата, но беда (не формата, как такового, а идеи хранения в нем типизированных данных) в том, что типизация в формате не предусмотрена (еще раз скажу, что это не проблема самого формата), конечно существуют различные механизмы описания, типа DTD, но для задачи хранения настроек это слишком... Как вариант, можно пойти своим путем (так сделала сама Майкрософт для своего продукта Virtual PC 2004) и хранить в xml-файлах информацию о типах элементов (благо формат позволяет делать это весьма элегантно). Я же, хочу рассказать еще об одном варианте "своего пути", личном ;) Так случилось, что мне пришлось писать собственную реализацию протокола XML-RPC, и сейчас, софт, который пишется, пишется с прицелом на этот протокол. Так вот, для хранения настроек и некоторых файлов с данными, было решено использовать формат пакетов XML-RPC (A, что может быть лучше? Тут, и строгая типизация, и богатый набор самих типов (да еще и парсинг уже написан и отлажен)). Сам протокол имеет только два типа пакетов methodCall и methodResponse, настройки логичнее хранить во втором, но чтоб не смущать пользователей любящих подкрутить что-нибудь руками тэгом <methodResponse>, я добавил третий тип пакета value (это не потребовало сколь нибудь значительной переделки генератора пакетов т.к. элементы value в любом случае сериализуются), который аналогичен пакету methodResponse, но где корневым элементом является value.

воскресенье, февраля 18, 2007

Очередной баг

Сегодня наткнулся на интересную особенность работы конструкторов записей. Имеем запись с полем типа Variant. В конструкторе, который, как известно, может вызываться сколь угодно раз для объекта/записи, присваиваем полю интерфейс получаемый из вновь создаваемого объекта. По идее, должно произойти освобождение старого объекта (если вызов не первый) т.к. ссылка на его интерфейс теряется, а затем назначение полю нового значения. Но при входе в конструктор, благодаря компилятору, поле получает значение Unassigned, в результате чего, мы имеем утечку памяти.

четверг, февраля 08, 2007

POPFile 0.22.4. Осьминог жукастый

Где-то, на просторах инета наткнулся на классификатор почты, POPFile, использующий теорему Байеса (Bayes) для отделения мух от котлет :) Нашел несколько хвалебных отзывов от его пользователей (говорят фильтрует аж 99.9% процентов спама), и самое главное, увидел, что он имеет XML-RPC API для взаимодействия с внешним миром. Не смог пройти мимо и не попробовать "повзаимодействовать" :) Качнув и установив его на виртуальную машину,  активировал работу XML-RPC API для внешних подключений (по умолчанию XML-RPC отключен). Дело за клиентом! По первому попавшемуся примеру сваял маленький пробник для перечисления корзин классификатора. И тут меня ждал неприятный сюрприз... Ошибшись в имени метода (пропустил одну букву) я получил в ответе некорректную (не соответствующую спецификации XML-RPC) fault-структуру, где член faultCode имел строковый тип... Выходит, используемая им перловая реализация (XMLRPC::Lite если я не ошибаюсь) кривая, коли допускает подобные вольности. Вот такие дела, авторам отпишусь :)

P.S. Вот и делай людям добро ;) Попытался отрапортовать об ошибке, так оказалось, для этого еще и на SourceForge'е нужно регистрироваться. Ну уж нет :)

P.P.S. На вызов метода release_session_key отдается структура, также не соответствующая спецификации XML-RPC (тэг <params> не имеет обязательных дочерних элементов).

вторник, февраля 06, 2007

Неудавшийся поиск

Что-то я ни как не могу найти фришный (собственно и платных не видел) монитор для XML-RPC :( Не просто проксю, которая будет показывать тела пакетов, а именно полноценный монитор с парсингом сообщений и раскладыванием по полочкам передаваемых значений (в древовидную структуру например). Что-то вроде майкрософтовского SOAP listener'а (вроде так называется). А если у него окажется еще и поддержка boxcarring'а и introspection'а, то ваще будет рай :) Уж больно не хочется самому писать...

четверг, февраля 01, 2007

"Приведение" типов

Правда не совсем приведение... Встала задача получить из TMemoryStream строку. Самый простой путь, он же и самый не эффективный,  задать строке размер SetLength и потом просто скопировать память с помощью Move. Неэффективность налицо: двукратно увеличеное требование к памяти и время на копирование. Но есть вариант проще:

  Type

TOpenedMemoryStream = Class(TMemoryStream);

Var

Data : PChar;

...

With TOpenedMemoryStream(AStream) Do
Begin

// Если выделенной памяти ровно столько сколько требуется потоку
// (обычно больше т.к. память выделяется блоками по 8192 байт)
// увеличиваем количество выделенной памяти не изменяя размера потока
If Capacity = Size Then
Capacity := Capacity + 1;

// Сразу за блоком, занимаемым потоком, записываем признак конца строки
// и сохраняем указатель на блок памяти для для последующей обработки
PByte(Integer(Memory) + Size)^ := 0;
Data := Memory;

End;

Теперь переменную Data можно приводить к строковому типу :)

Исходники

На домашней страничке выложен архив (~8Kb) содержащий модули и шаблон для создания мультиформенного приложения (MS Office 200 like).

четверг, января 25, 2007

День под знаком "петли"

Сегодня у меня был ужасный день... На моей Тоше (Toshiba Satellite Pro M30) жутко расхлябалась левая петля :(. Такое случалось и раньше, но там я обходился малой кровью, а именно: снимал с петли накладку (снимается она легко) и под две скрепленные заклепкой пластины (между которыми и образовывался люфт) подкладывал всяческие железки. Это помогало, но на некоторое время. Я прекрасно понимал, что раз оно заболталось, значит с одной стороны у заклепки отваливается шляпка, но с какой было не ясно. Операцию подкладывания я проводил целых три раза, и вот сегодня свершилось... Люфт стал настолько большим, что при открывании крышки накладка петли сама-собой отщелкивалась :(. Ничего не оставалось делать, как разобрать бук и посмотреть на виновницу "торжества". Как я и предполагал, нижняя шляпка заклепки отвалилась наполовину. Пришлось вооружаться плоскогубцами и пилкой по металлу т.к. заклепка выниматься не желала. Получасовая битва наконец принесла свои плоды, заклепка сдалась! Я подыскал подходящий по размеру болтик с "гравером" и гаечкой и принялся восстанавливать работоспособность железного элемента. Наконец все закончено и бук можно собирать! Ура! Сборка прошла весьма успешно и я был уже готов включить его и проверить на "мало ли чего", как вдруг вспомнил, что не поставил накладку на петлю. Ну-да, дело плевое, не первый раз, решил я, и принялся накладку устанавливать. Но, не тут-то было... Гаечка оказалась слишком толстой, и накладка, ни как не хотела надеваться на петлю :(((( Щьёрт побьерьы!!! Снова разбирать бук... Это был сильный стресс... Но делать нечего, пришлось вновь разбирать до винтика (если кто разбирал эту модель, поймет, там снимать нужно все вплоть до HDD и CD). После разборки и поиска замены толстой гаечке, я обнаружил, что заменить ее нечем :((((( На помощь пришел напильник, коим я старательно обтачивал гайку, а заодно и головку болта. Покончив с этим делом, и примерив накладку (она наделась просто чудно) я решил, до кучи, еще и кулер смазать литолом! Надумано - наделано! Кулер смазан, накладка надета, осталась сборка. Сборка заняла минут пять, потом влажная уборка рабочего места и протирание матрицы и самого бука. У-ф-ф-ф... Зато теперь петля никуда от меня не денется ;)

вторник, января 23, 2007

Наследование записей

Ну не так, чтоб уж совсем наследование, но механизм расширения функционала рабочий. Итак: определяем запись TRecord с неким множеством методов. Затем (типа наследуемся) определяем запись TRecordDesc = Type TRecord. Теперь эти записи не совместимы (для чего это нужно - ниже). Описываем Record Helper For TRecordDesc с неким множеством методов/свойств. В итоге, мы получили функционально расширенную запись, ну а несовместимось нужна была, чтоб члены record helper'а не попали к предку. Однако копирование записи достигается простым приведением типа ;) Если бы хэлперы позволяли описывать перегрузку операторов, можно было обойтись и без приведения.

Однако есть еще способ ;). Можно использовать агрегацию, тем самым избавиться от хэлперов и приобрести возможность перегружать операторы :).

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

Где, блин, революция!?

Еще, когда только планировалась к выходу Delphi 6, весь инет шумел о веб-сервисах, все говорили, что вот, грядет оно, светлое будущее. И собственно где? Ну блоги, понятное дело, ну еще г-н Орейли чего-то там сделал, ну да, г-н Виннер, а еще? Публичных веб-сервисов кот наплакал, да и те умеют лишь рапортовать о валюте, времени да погоде... Это я к чему, да просто г-н Балмер недавно снова предсказал революцию веб-сервисов в течении ближайших 10 лет :).

Что еще интересно, по задумке идеологов, веб-сервисы должна была объединить одна важная особенность - протокол взаимодействия (тогда на это точили SOAP, а Borland даже сделала RTTI для интерфейсов в шестой версии). И взгляните, что происходит сейчас: образовалась целая куча подходов к осуществлению взаимодействия (SOAP, XML-RPC, REST, JSON, PI-RPC, AJAX и.т.д), каждый считает себя самым умным и делает то, что считает нужным. Например контора на "Г" прибила бету поискового сервиса на SOAP, и перевела его на AJAX (чего уж не на GData).  Таже контора обещает отломать от Blogger'а XML-RPC API и перейти на что-то свое... Короче, разброд полнейший... Что-же касается SOAP, то он уже давно превратился в монстра с которым, никому, кроме породивших его Франкенштейнов, связываться не хочется.

воскресенье, января 14, 2007

Что делают в армии?

На этот вопрос каждый отвечает себе сам :) Я пошел в армию вполне осознанно, бросив учебу в университете. Пошел, потому что так было надо (ну воспитывали нас так), т.е. все нормальные косили, а остальные шли служить. До этого я учился в техническом лицее, где получил диплом программиста и к тому времени писал на Clipper'е, Turbo Pascal'е и Assembler'е. Имея первое место "на республике" по программированию, и соответствующий диплом, я наивно полагал, что в армии тоже буду программировать :) Но так в общем и вышло ;) Служил я в РВСН в/ч 44200, прикомандированным к центру психологической работы. Программировал в основном психологические тесты разных мастей по именитым методикам, но такая работа мне не очень нравилась, хотя и напрягала не особенно. Но кроме этого довелось мне писать две интересные программы: первая - расчет заработной платы военнослужащих, а вторая - мой дембельский аккорд (оптимальное распределение военнослужащих). О второй писать не буду т.к. писать придется слишком много :) Ну а первая, вот она:

 Написана на Borland Pascal 7.1 with objects. Работала под DOS, в режиме 640 x 480 x 4. В качестве базы данных использовался самописный движок для работы с .dbf (это была моя дипломная работа в лицее). Для программирования интерфейса импользовалась также самописная библиотека. Жаль, что в то время, я ни как не мог въехать в прелесть ООП и библиотека по сути состояла из объектов, но представленных весьма специфично ;) (т.е. каждый объект был записью которая манипулировалась неким множеством процедур и функций). Программа расчета  имела возможность создавать архивные копии данных при переходе на новый месяц, была предусмотрена система справочников, а для простоты изменения алгоритма расчета мне пришлось добавить поддержку формул, для чего был написан синтаксический анализатор (как же мне было трудно и интересно ;)) По интерфейсу было решено закосить под недавно вышедшую Windows 98, отсюда и название такое ;) Мне даже было не влом сделать поддержку цветовых схем аля Windows (см. следующий скриншот)

 

 

 

 

 

 

Программа получилась даже очень ничего ;) и была внедрена в одной из воинских частей, за что я был премирован новой шоколадной "афганкой" (кто служил тот поймет ;) Вот этим я занимался в армии :)

пятница, января 12, 2007

Ностальгия...

Сегодня наткнулся на скриншоты своей (ну писал-то я ее не один, нас было двое, но скрины только моего творчества ;)) первой и единственной корпоративной (как это модно сейчас называть) системы. Чего-то воспоминания нахлынули... В общем вот:

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

Далее опишу, как происходило обновление клиентских приложений.Диалог обновления Ввиду того, клиентские места были очень сильно разбросаны территориально (удаленные цеха, промыслы. самый дальний ~120км), проблема обновления ПО не решалась методом беготни с дискеткой по офисному зданию. Поэтому соответствующий функционал был заложен в серверную часть еще на стадии проектирования. Реализовано все было очень просто: сервер имел самые последние версии исполняемых модулей, разработчик делая билд (т.е. увеличивая версию) при подключении к серверу публиковал измененный модуль. Когда клиент подключался к серверу, тот проверял версии модулей клиента и имеющиеся у него новые и в случае необходимости, клиенту сливались обновленные версии.

Процесс публикации отражен на следующем скрине:

Пример UI сервераЭто не боевой сервер, скрин был сделан специально для демонстрации состояний клиентских подключений. В динамике все выглядело очень эффектно :), при каждом новом запросе, мониторчик клиента мигал, было сказачно красиво ;).

Моим первым приложением был "Электронный табель" позволявший на местах (в цехах, на промыслах) вести электронный учет рабочего времени, что позволяло отделу кадров оперативно отслеживать ситуацию на рабочих местах и вносить соответствующие коррективы. Но скрина этого приложения у меня не сохранилось, вместо него публикую скрин приложения "Отдел труда и зарплаты",ОТиЗП которое полностью повторяло функционал ведения табеля, но кроме этого делало еще массу полезных вещей :). На этом скрине видно большое меню, которое формировалось  (т.е. выполнялся весьма приличный запрос к серверу и по результатам строилось меню) в момент клика пользователем на соответствующем пункте. Работало очень даже шустро :)

Затем было написано приложение "Банковские операции", но его скрина у меня тоже не сохранилось. После отработки по банкам, я сел за приложение "Кассовые операции", скрин которого приведен ниже.Кассовые операции Это было достаточно простое приложение, но в нем был один интересный (в то время) для меня момент: его нужно было интегрировать с веб-сервером разработчиков (т.е. не корпоративным, а именно девелоперским, т.е. нашим) т.к. на сервере работал скрипт завязаный на сторонний софт, и тащить тот софт на клиента не было ни какого желания (это только добавило бы головной боли). Почему именно веб? А почему нет! :)

Затем мне пришлось возвращаться к старой теме (дело в том, что ранее я уже писал для этой конторы сию прилагу, но только под ДОС, и по договору т.е. я там еще не работал) и писать приложение "Подотчет".Подотчет Изюминкой этой работы для меня стала реализация "мультиформенного" приложения т.е. приложения без главной формы (office2000 like). Решилась проблема достаточно просто и эффективно, правда пришлось сильно попотеть изучая механизмы взаимодействия различных частей VCL, чтоб обеспечить корректность работы в таком режиме. Особенно это касалось модальности окна только для активной формы.

Ну и наконец скрин боевого сервераБоевой сервер. На скрине открыт диалог настройки с назначением прав пользователя. Пользовательская база была интегрирована с базой MS-SQL на котором и крутилась вся система. На SQL сервере было всего 25 лицензий, но за счет серверной части нашей системы (т.е. по сути ее второго уровня) на этих лицензиях работало ~70 целовек :) (я делал стресс-тестирование, сервер выдержал 150 подключений, но не выдержала моя рабочая машинка :))  Я тогда считал, мы экономили для конторы примерно $20К :) (сейчас вероятно цена уже не актуальна). Сервер вел подробнейшие логи работы пользователей, все запросы падали в лог, поэтому мы всегда могли отыскать любые концы :) (и это было важно ввиду некоей борьбы между двумя отделами). Т.к. система работала на BSS (Borland Socket Server) (знаю, что плохо, но это был единственный приемлемый вариант) у нас были частые проблемы с обрывами связи (т.к. сам BSS кривой, да и инфраструктура нашей сети была далека от идеала), поэтому в серверную и клиентскую части был добавлен функционал обеспечивающий механизм сессий и решавший таким образом проблемы с обрывами.

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

p.s. Еще и армейскую работу вспомнить, чтоль...

четверг, января 11, 2007

Еще один Free

Обнаружил, что HTML Display Components стали бесплатными! Идеальное решение для HTML-интерфейса или отчетов в приложениях. К плюсам можно отнести независимость от сторонних движков и их версий, вследстие чего, однозначное отображение на любой системе. К минусам - не самое быстрое форматирование контента и скромные возможности управления внутренними объектами вследствие отсутствия поддержки DOM. Но мне, все равно, очень нравится ;)

понедельник, января 01, 2007