Tech Articles


Breaking Platform Limitations


One of the innovative new features in the PowerBuilder 12.5.1 release is its ability to deploy PowerBuilder .NET code to run in 64-bit mode on 64-bit Windows platforms. In this article, after gaining background and perspective on 32- and 64-bit memory management and .NET deployment models, you'll explore the internals, strengths and limitations of this new feature.

Introduction
Almost all current server, desktop and notebook hardware platforms have 64-bit processors. Almost all current versions of Windows operating systems support both 32- and 64-bit platforms. With the 12.5.1 release, some PowerBuilder application software will be able to take full advantage of all available system memory. Read on to see if your code is a candidate for instant memory expansion.

Background
32-bit OS' can access a theoretical maximum 4 GB of RAM. In practice however, 32-bit Windows employs a 4-GB tuning model in which an application gets only 2 GB of virtual memory while the remaining 2 GB are assigned to the OS kernel. So the realistic maximum application memory is limited to 2GB. This limitation can only be released if the application was compiled with the /LARGEADDRESSAWARE option and the /3GB switch is set. In this situation, the application can get up to 3 GB of memory. (See PowerBuilder documentation on how to make the compiler large memory aware if you run out of memory when compiling your application.) PowerBuilder applications, not being large address aware, are therefore limited to 2GB RAM.

The main benefit of a 64-bit OS is the amount of memory it can reference. A 64-bit OS can theoretically address a huge address space. Linux supports 64 TerraBytes of physical memory. Windows artificially limits how much RAM can be used as a tactic to make users upgrade to more expensive versions when they want more RAM. Windows 7 Starter is limited to 2GB, Home Basic to 8, Home Premium to 16, and Professional and above are limited to 192GB. Windows Server releases can have far higher limits for up to 2TB (see http://superuser.com/questions/168114/how-much-memory-can-a-64bit-machine-address-at-a-time or http://msdn.microsoft.com/en-us/library/windows/desktop/aa366778(v=vs.85).aspx for a complete discussion).

But let's face it, most PowerBuilder business applications will not consume more than 1 GB of memory. Why care about large memory allocation? To answer this question, let's take a moment to clarify what more RAM can (and can't) do. The biggest benefit of upgrading a PC's memory is better multi-tasking, especially when running RAM-intensive applications like Photoshop, Outlook, or Internet Explorer. Having a lot of memory means quickly switching between applications without Windows writing process memory out to the pagefile. (The pagefile performs much the same purpose as RAM, but the data is stored on your much slower hard drive.)

More RAM does not make a PC faster; it just allows it to do more things at once. If a single application uses 200 MB of RAM, it won't matter if there are 2 or 8GB of total system memory, but if there are 10 windows open using 200 MB each, there probably can be benefits to a memory upgrade (see http://lifehacker.com/5415355/do-you-really-need-more-than-4gb-of-ram.)

Why not run all programs on a 64-bit OS? The answer is tied to a device driver or unmanaged code dependencies. Device drivers designed for 32-bit Windows won't work on computers running 64-bit Windows. If you're trying to install a printer or other device that only has 32-bit drivers available, it won't work correctly on a 64-bit version of Windows. Likewise, unmanaged code written using 32 bit libraries won't work correctly on a 64 bit OS.

WoW64
You can have your cake (64-bit OS) and eat it too (32-bit process) because the WoW64 (Windows 32-bit on Windows 64-bit) subsystem is included on all 64-bit Windows versions. WoW64 automatically runs 32-bit applications in full emulation mode on a 64-bit OS. See http://en.wikipedia.org/wiki/WoW64 and http://msdn.microsoft.com/en-us/library/aa384274(v=vs.85).aspx for more information. Note that you must install both the 32-bit version and the appropriate 64-bit version of the CLR to run .NET code on a 64-bit Windows platform. WoW64 has a processor architecture-specific implementation so performance is not linear across platforms. However, some have noted some performance degradation because the processor must switch into and out of emulation mode to run the application (see http://www.viva64.com/en/l/0002/print/ for more details).

What to Do When WoW64 Is Absent?
Windows Server 2008 R2 has an operational mode called Server Core. Server core installs the OS without the GUI. Under Server Core there is only command line support. Also, under Server Core, support for 32-bit applications is optional by default. Launching a 32-bit application in Server Core mode will fail with an informational message when there is no 32-bit support. Because Server Core can only run 64-bit applications, 64-bit support is imperative. Therefore PowerBuilder .NET Web Services running inside an IIS server under a Server Core OS must have pure 64-bit support.

.NET Compilation Models
.NET supports three CPU compilation models; x86, x64 and Any. (There is actually a fourth, Itanium, which we'll not consider.) The Any CPU model is processor-agnostic; it will just-in-time (JIT) compile to 64-bit code when loaded into a 64-bit process and to 32-bit when loaded into a 32-bit process. However, by choosing an x86 CPU compilation model you are generating code that can only be run in a 32-bit process. In essence you are saying there is something being used by the code assemblies (usually unmanaged code) that specifically require a 32-bit platform. Similarly setting the project to x64 will specify that the assembly must run under 64-bit Windows. By limiting the CPU to x64 you are saying that there is something in the code that specifically requires 64-bits. Attempting to run a 64-bit only assembly on 32-bit Windows or call the assembly from a 32-bit process will result in a runtime error. However, if an app is compiled as x86, it will be run by the x64 system in WoW64, and it will be able to load 32-bit DLLs.

Another important fact to understand is that .NET called code assumes the bit-ness of its caller. An Any targeted assembly that is called by an x86 executable is JIT compiled to 32-bit code. Likewise an Any targeted assembly that is called by an Any executable running on a 64-bit OS is JIT compiled to 64-bit code.

The PowerBuilder .NET Story
As you can see in the screenshot from .Net Reflector in Figure 1, PowerBuilder 12.0 .NET assemblies were compiled using an x86 platform model. The same is true for both v12.1 and v12.5.0 runtime assemblies. This means that these PowerBuilder .NET versions can only run on a 32-bit platform or under WoW64 on a 64-bit platform using the memory allocation mechanisms these platforms provide.

Figure 1: PowerBuilder 12.0 x86 Assembly

Similarly, as you can see in Figure 2, PowerBuilder .NET 12.0 application, assembly and web service targets compile using the x86 model. No support for other memory models was provided.

Figure 2: PowerBuilder 12.0 x86 Executable

Why the 32-bit limitation? Because PowerBuilder depends on lots of 32-bit managed and unmanaged code. Removing and replacing that code has been a major ongoing refactoring and enhancing effort. Finally in version 12.5.1 engineering has presented us with a nearly 32-bit code free platform

Enter PowerBuilder 12.5.1
Engineering did a lot of work in the 12.5.1 runtime. As you can see from Figure 3, all the runtime assemblies are now compiled to the Any platform target. That means they can run on both 32- and 64-bit platforms.

Figure 3: PowerBuilder 12.5.1 Any Platform Assembly

Additionally, the WPF Application project object painter was enhanced to allow you to select the code model used to generate your EXE code. Figure 4 shows the 12.5.1 project object painter with the new Platform Target option highlighted. You can plainly see the two platform options, 32-bit (generates x86 code) and 32-bit or 64-bit (generates Any code). You choose the appropriate platform target for your deployment. The deployer does the rest. It's important to note that only the project object in a WPF Application Target has a Platform Target option. Table 1 shows how compiler options affect the way PowerBuilder applications are run on the various platforms.

The other target types (PB and .NET Assembly and WCF Service) generate code that is always called by other code. Their bit-ness is determined by that of the caller. Assemblies and Services default to the Any platform type. Flash! PowerBuilder assemblies can now be called by C# x64 or Any code format applications. IIS running 64-bit can now host PowerBuilder 12.5.1 generated assemblies and PowerBuilder Web Services.

Project Object: App EXE Format

Platform

CLR JIT bit Format

PB Assembly Format

Emulator

32-bit

32-bit

32-bit

32-bit or 64-bit

None

32-bit

64-bit

32-bit

32-bit or 64-bit

WOW64

32-bit or 64-bit

32-bit

32-bit

32-bit or 64-bit

None

32-bit or 64-bit

64-bit

64-bit

32-bit or 64-bit

None

Table 1: Compiler option runtime effect

 

Figure 4: Platform Target option

Are We There Yet?

You know the feeling. It's been a long drive and you're sitting in the back seat without a clear picture of when you'll arrive. So are you there yet? Let me tell you where the platform is today and you can decide if you're there.

As mentioned above, all PowerBuilder runtime assemblies target the Any platform and you can select the target platform code format in which to generate your own assemblies (exe is an assembly). However, even though the vast majority of platform functionality is Any platform compliant, not all functionality in the 12.5.1 runtime assemblies is free of 32-bit dependencies. Some code in a few runtime assemblies still interoperates with C++ managed 32-bit libraries. Figure 5 shows an example of a PowerBuilder runtime assembly having a 32-bit dependency. Code in this assembly, if invoked by PowerScript code in your application running in pure 64-bit mode, will throw a BadImageFormatException exception. Your application will shut down if this exception is left unhandled.

Figure 5: PowerBuilder runtime assembly with 32 bit dependency

Here's a list of functionality with 32-bit dependencies that will perform properly when invoked in x86 mode but will throw an exception when invoked in a 64-bit context:

  1. All non-ADO.NET database drivers (You can only connect to a DB using a 64 bit compatible ADO.NET driver). Figure 6 shows one such ADO.NET compatible DB provider
  2. OLE functionality. Most ActiveX controls are 32 bit
  3. MailSession functionality (PowerScript MAPI functionality)
  4. String functions ending in "A" such as FillA and LeftA (These functions are only used in DBCS environments. "A" functions temporarily convert a string from Unicode to DBCS based on the current locale then return the number of bytes NOT the number of characters. You should be invoking the Non-"A" functions such as Left and Right which tell you the number of characters, not the number of bytes.)
  5. Reading PSR files
  6. <>SaveAs( Excel8! )
  7. MobiLink Synchronization

Figure 6: ADO.NET 64 bit compatible DB provider

If your code has or depends on any of the above mentioned functionality, what you must do to run it on a 64-bit platform depends on the Target type. If the code is in a WPF application, choose the 32-bit Platform Target option when building the EXE. Windows will run the app and load all its assemblies in WoW64 mode. If it's in a WCF Web Service, configure the hosting IIS or application pool to "Enable 32-bit application." IIS or the application pool will run in WOW64 mode.

Other Caveats, Tips and Workarounds
The PowerBuilder.NET IDE will continue to require a 32-bit OS. It will run on WoW64. Consequently you will not be able to Debug code running pure 64-bit. You will continue to be able to debug code running under WoW64.

It would be useful to have a code analysis or migration tool that would scan a Target and warn about potentially problematic code. Unfortunately, the PowerBuilder toolset does not supply such a tool. Currently you have to manually search your code for potential issues.

If you want your code to be dual platform compatible, .NET 4.0 provides a property you can test to determine if an app is running on a 64-bit platform. Figure 7 shows the property.

Figure 7: 64-bit test property

As you can see in Figure 8, the PFC platform service relies on 32-bit external libraries. In this particular case, Microsoft used the used the "32" suffix for its 64-bit DLLs to minimize migration impact, so no change is necessary. However, when migrating applications that rely on custom 32-bit external functions, you will need to recompile those functions to be compatible with a 64-bit platform.

Figure 8: PFC Local External Functions

Conclusion
Engineering has done a yeoman's job of delivering an almost feature complete 64-bit compatible compiler and runtime platform. However, it looks like we'll have to wait until version 15 for any pure database driver compatible 64-bit compatibility. At that point I expect the 64-bit deployment floodgates to open wide.

 

--This article was originally published on PBDJ.

Comments (0)
There are no comments posted here yet

Find Articles by Tag

CI/CD Source Code BLOB JSONParser PostgreSQL ODBC driver Import Validation NativePDF PowerServer Web Configuration Database Profile Resize JSONGenerator SOAP InfoMaker SQL SqlModelMapper Database Table Schema OrcaScript RESTClient PFC Database Object RibbonBar Builder Outlook Text Event Handler Messagging Event Branch & Merge Excel WebBrowser Filter SnapDevelop DataType Application Source Control Design Import JSON Script Web Service Proxy UI Modernization Error Authorization PowerBuilder (Appeon) OLE Trial Model Deployment iOS Event Handling Window .NET DataStore Platform Repository License Expression Interface CoderObject Azure Export JSON GhostScript Testing COM Encoding UI DLL Class SQL Server UI Themes Array Transaction Android TLS/SSL IDE PowerServer Mobile RibbonBar Performance File Syntax ActiveX Database Connection .NET Std Framework DataWindow JSON REST Elevate Conference PowerBuilder Compiler Web API Database Table XML PowerScript (PS) Debug TortoiseGit Data TFS HTTPClient Charts WinAPI Installation Windows OS Migration Export C# PBDOM JSON SqlExecutor Variable OAuth Windows 10 Icons CrypterObject Database Table Data 64-bit DevOps PDF .NET Assembly OAuth 2.0 Icon TreeView MessageBox Graph Bug Linux OS RichTextEdit Control 32-bit Git SVN External Functions ODBC PowerBuilder PostgreSQL DragDrop Service Encryption Debugger Menu Debugging Sort Oracle Stored Procedure Open Source Jenkins Authentication Database Painter Mobile SnapObjects Database DataWindow Automated Testing API SDK PDFlib