четверг, 29 сентября 2016 г.

А Вы перешли на WIN64?

Однажды я писал о переходе на Unicode. Теперь настало время адаптации приложений под Win64.

Собственно план такой же, как и раньше:
  • обновление сторонних библиотек и компонентов;
  • адаптация наших библиотек;
  • тестирование, тестирование и ещё раз тестирование.
Обновление сторонних библиотек и компонентов прошло почти без потерь. Из нетривиального:
  1. Пришлось повозиться со связкой TB2k + TBX + старенький (альфа версия) SpTBX. TB2k - это тулбары и контекстные меню в стиле Office2000. TBX - это набор наследников от TB2k, плюс несколько дополнительных компонент, а самое главное - это темы оформлений (под офис XP, 2003 и т.п.). SpTBX - это набор наследников уже от TBX с завязкой на библиотеку TNTComponents, которая позволяет использовать Unicode в неюникодных версиях делфи.
    Под x64 оно в том виде, как у нас используется - так просто не компилируется, т.к. есть ASM-код. А ещё там свои циклы обработки сообщений и хуки на основную очередь сообщений...
    Обновлять эту связку - дело такое... TBX для реализации тем делает патч на TB2k, при этом его развитие прекратилось уже давно, в связи с чем новые версии SpTBX отвязались от TBX и стали несовместимы со старыми версиями.
    Вобщем получилось так: TB2k обновилось без проблем (правда с предупреждением, что в x64 оно не оттестировано). TBX я нашёл на гитхабе (Юрий, спасибо Вам). SpTBX оставил старенькую альфа-версию, пришлось вырезать из неё завязки на TNT и что-то по мелочи в связи с обновлением первых двух.
    Ну и после всех обновлений внёс все правки и исправления, которые появились у нас за годы использования предыдущих версий компонентов.
  2. Библиотека TntComponents. По факту не используется с момента перехода на юникод, но по всем проектам полно ссылок на модули в uses. Тупо замена всех TTnt на T и удаление из uses. (Наконец-то! :)
  3. Старенький модуль QStrings. От него тоже пора отказаться, т.к. он работает только с Ansi-строками. Но слишком много на него завязок. А так просто под WIN64 он не компилируется, т.к. в нём почти всё на x86-ассемблере.
    В общем, провозился с ним дольше всего: выкинул неиспользуемые процедуры, затем весь ASM-код заменил нативным (для некоторых функций нашёл замену из JclStrings и JclMime, некоторые функции пришлось писать самому). Не обошлось и без правок наших unit'ов. 
  4. UCE (Unicode Syntax Editor) - от создателя Virtual Tree View, давно не развивается и завязан на библиотеку Unicode, в которой полно ассемблера. Пока не определился что с ней делать, адаптировать конечно можно: там ассемблер вполне заменится на стандартные процедуры/функции. Но оно используется у нас только в одном месте, и то, оставлено только для обратной совместимости. Поэтому, скорее всего, из 64-битной версии приложений я её просто исключу.
Всё остальное, либо гуглится без проблем, либо уже готово к WIN64.
Итого на обновление и адаптацию всех сторонних библиотек ушло около 30 часов. Теперь дело за нашими исходниками (а некоторым из них уже 15 лет!) и тестами. На сегодня приложения под WIN64 собираются и даже работают, но я знаю как минимум об одном подводном камне: Integer <--> Pointer преобразования (Pointer уже 8 байт, а Integer - всё ещё 4), к сожалению их не мало. Ну и из замеченного - экспорт данных в эксель через оле - передаёт пустые ячейки (но, думаю, там тривиально). [UPD: действительно тривиально: при подсчёте ширины столбцов заменил обычное деление на целочисленное - и всё заработало.]

Ах да, ещё Oracle Instant Client нужен 64-битный. Тут всего один момент: почему-то последние лайт-версии клиента валят ошибками, поэтому мы остановились на 10.2.0.5, благо оно пока ещё доступно для скачивания.

А вы поставляете 64-битные версии приложений своим клиентам?

P.S.: Порадовала возможность прозрачной отладки 64-битного приложения из 32-битной среды разработки.
P.P.S: SendMessage окну другого приложения из-под отладчика не работает, или работает неправильно. Пока не понял.

17 коммент.:

Chaa комментирует...

64-х битный отладчик хуже 32-х битного, по крайней мере в XE5.
На проекте, состоящем из нескольких DLL, постоянно возникают проблемы с отладкой.
Еще люди жалуются на медленный RTL. Но в общем-то работать можно.

Mark комментирует...

в x64 счетчики и некоторые важные переменные во внутреннем коде списков (например TList.Count) остались Integer т.е. 32-бита

Анонимный комментирует...

Вы бы поделились обновленным TB2k...

Николай Зверев комментирует...

Mark, Вам действительно надо хранить в динамическом списке более 2^31 элементов?

Анонимный, тынц

Fr0sT комментирует...

C одной стороны, особой необходимости в х64 версиях для неспециальных программ нет - все и так работает. С другой - х32 версии медленней в обращении с 8-битными числами, и если таковые широко используются - х64 версия может выиграть в производительности. Однако код многих базовых функций в RTL написан так неоптимально, что скорость таких операций, как Pos падает в несколько раз. В итоге без необходимости я бы переходить не стал. Но адаптировать код, имея в виду эту платформу, безусловно стоит (я про то же "прозрение", что случилось после появления Юникода: что нельзя кастить Char к Byte, так же и здесь нельзя кастить Pointer к Integer). Конечно, грамотный код и так от этого избавлен, и в идеале переход на х64 вообще не потребует никаких изменений, кроме, разве что, некоторых WinAPI функций.

Александр Алексеев комментирует...

С преобразованиями Int-Ptr - намучаешься. В отличие от перехода на Unicode, в компиляторе Delphi (в отличие от FPC) отсутствуют аналогичные warning-и для перехода на x64, поэтому остаётся спасаться только повсеместным включением range checking и отловом в run-time, что затянется надолго.

Николай Зверев комментирует...

Александр Алексеев, угу, поэтому я и пишу в следующей заметке про ключевые слова для поиска. Т.е. search and review. Плюс RunTime-тестирование, без этого никак.

Ruzzz комментирует...

А вот интересно тип индекса (счетчика) для динамического массива имеет значение?

Николай Зверев комментирует...

Ruzzz
Откройте System.pas, там можно найти примерно такое:

  TDynArrayRec = packed record
    RefCnt: LongInt;
    Length: NativeInt;
  end;

А также:
  function __DynArrayLength(const A: Pointer): NativeInt;

Т.е. длина динамического массива - это NativeInt.
При этом в справке оно описано по старому:
  function Length(S: string or dynamic array): Integer;

Возможно для динамических массивов генерируется NativeInt, но это уже надо смотреть выходной asm.

Ruzzz комментирует...

Да это самое первое что сделал.
Я имею ввиду, будут ли какие-то накладные расходы, например если 32 битный счетчик, индекс под 64бит.
Установлю 64-битный компилятор, поизучаю.

Александр Люлин комментирует...

Да. Хуже. Медленнее. И исключения перестаёт показывать.

Александр Люлин комментирует...

И покрытие тестами ;)

Александр Люлин комментирует...

На самом деле все иструкции 64битные. Что mov rax, rcx, что mov eax, ecx. Это в интеловской спецификации написано.

Александр Люлин комментирует...

Есть небольшой хинт. Весь ассемблер для начала тупо изменяем на assert. Под ifdef CPU64. И запускаем тесты. И разбираемся уже по факту. По мне - сильно время экономит.

Александр Люлин комментирует...

Написать на асм можно и под 64 бита. Но всё время надо помнить о том, что вызывающая функция должна распределять фрейм для spill регистровых параметров. Поэтому по факту просто написать только листьевые функции. Поэтому парни с rtl и не стали заморачиваться. Ну а pos можно и свой написать. Если действительно тормозит.

Александр Люлин комментирует...

Компилятор местами ругается на преобразования. За что ему спасибо.

Александр Люлин комментирует...

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

(Оригинальная цитата - "The caller reserves space on the stack for arguments passed in registers. The called function can use this space to spill the contents of registers to the stack.")"

Отправить комментарий

.

.