четверг, 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 окну другого приложения из-под отладчика не работает, или работает неправильно. Пока не понял.

18 коммент.:

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 функций.

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

С преобразованиями 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-битный компилятор, поизучаю.

Alex W. Lulin комментирует...

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

Alex W. Lulin комментирует...

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

Alex W. Lulin комментирует...

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

Alex W. Lulin комментирует...

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

Alex W. Lulin комментирует...

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

Alex W. Lulin комментирует...

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

Alex W. Lulin комментирует...

"Также спецификация вызова обязует вызывающую процедуру распределять место в собственном стековом фрейме для временного сохранения (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.")"

Anton Alisov комментирует...

Николай, можете скинуть исправления TB2K и SpTBX под 64-битную компиляцию? alan008@bk.ru

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

.

.