Friday, May 21, 2010

The power of shift clicking – Copy As Path

 

copyaspath

Have you ever been in explorer and needed to get the path of a file?

Turns out that feature is built into Windows 7! If you shift right click on a file, the menu contains a copy as path link.  Sweet!

Saturday, May 15, 2010

Making the FSharp interpreter (fsi) run in 64bit!

I love F#!  It’s all the power of functional programming with the training wheels of c# when you need it. All the prototype/REPL power of powershell and python, with the built in test cases I like to call static typing. All the power of static typing, with out the hassle of specifying types every where thanks to implicit typing.

But, there is one annoying problem, I crunch very large data sets and fsi.exe runs as a 32 bit application. This means when I load my data sets and iterate through them FSI takes up 1.6 GB of RAM (maximum for a 32bit app), and spends 100% of its time in GC.

An aside for you who are thinking: 1.6GB is enough RAM!? – Igor must be a really crappy programmer!!! 1.6GB could be plenty, but why should I spend time adding complexity to my code when I have a superb memory manager, a 64 bit address space and a 3 year old dev machine that has 16GB of RAM, and 8 processors?  Today, I get no value from optimizing my data set for memory utilization -- I’m better off making my data cruncher a 64 bit application.

Back to work.  First, lets open up the Visual Studio command prompt (it has the tools we need in its path) and find fsi.exe.

C:\Program Files (x86)\Microsoft F#\v4.0>dir fsi.*
Volume in drive C has no label.
Volume Serial Number is 8EDE-D64E

Directory of C:\Program Files (x86)\Microsoft F#\v4.0

03/19/2010 02:02 PM 230,216 Fsi.exe
09/30/2009 08:08 PM 158 Fsi.exe.config
2 File(s) 230,374 bytes

Lets make sure it's 32 bit - we do that with a tool called corflags.

C:\Program Files (x86)\Microsoft F#\v4.0>corflags fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1

Next we use corflags to make fsi 64bit. This will unsign the fsi.exe but this hasn't affected anything for me yet.

 

C:\Program Files (x86)\Microsoft F#\v4.0>corflags /32bit- /force fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

corflags : warning CF011 : The specified file is strong name signed. Using /For
ce will invalidate the signature of this image and will require the assembly to
be resigned.

Lets double check it worked:

 
C:\Program Files (x86)\Microsoft F#\v4.0>corflags fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1

Finally fire up F#, and it's now in 64 bit - yippee!

Friday, May 7, 2010

The joy's of batch - Delayed Expansion

 

If you can, skip batch and move strait to powershell. If you don't believe me, maybe this blog post will change your mind. In batch %ErrorLevel% is how you know if the last command succeeded:

C:\>echo %ERRORLEVEL%
0

It turns out if you set a variable that doesn't exist, this sets error code to 1. So

C:\>set DONKEYRIDING
Environment variable DONKEYRIDING not defined

C:\>echo %ERRORLEVEL%
1

Makes sense, batch isn't that bad you think. Now here's a pop quiz - What will you get when you run this batch file?

C:\>type foo.bat
if NOT "BATCH"=="OBVIOUS" (

echo %ERRORLEVEL%
set DONKEYRIDING
echo %ERRORLEVEL%

)

I"ll run it for you:

C:\>foo.bat

C:\>if NOT "BATCH" == "OBVIOUS" (
echo 0
set DONKEYRIDING
echo 0
)
0
Environment variable DONKEYRIDING not defined
0
C:\>

Not what you thunk huh? Maybe error level wasn't set - lets check

C:\>echo %ERRORLEVEL%
1

What the heck happened? Well, the if block is a statement, and variable substation happened when the statement was read.  You don't want this behavior and you’re probably not interested in the details, luckily batch has something called delayed variable expansion, which you expose using !ERRORLEVEL! so you need to change your batch file to be:

setlocal ENABLEDELAYEDEXPANSION
if NOT "BATCH"=="OBVIOUS" (
echo !ERRORLEVEL!
set DONKEYRIDING
echo !ERRORLEVEL!
)

Which gives the expected output:

C:\>foo2.bat

C:\>setlocal ENABLEDELAYEDEXPANSION

C:\>if NOT "BATCH" == "OBVIOUS" (
echo !ERRORLEVEL!
set DONKEYRIDING
echo !ERRORLEVEL!
)
0
Environment variable DONKEYRIDING not defined
1
C:\>

As I said, skip batch and go strait to powershell!