Feeds:
Posts
Comments

Archive for April, 2007

More Vista Hate

What was Microsoft thinking? It seems to me that they owe a lot of their success on maintaining backwards compatibility. In contrast to earlier versions of Windows, of the first seven pieces of software I tried on Vista, just two have worked without any issues (Firefox and Office 2007), the others in no particular order are:

  • MinGW C++ compiler (this is working now that I replaced one of the DLLs)
  • Chicken scheme compiler
  • Office 95 (I only have a non-commercial license for Office 2007 – what if I want to sell my writing ;))
  • MSN Messenger (I’ve spent two hours on various attempted solutions – still not working)
  • The ZoneAlarm personal firewall (admittedly, Vista has its own, built-in firewall)

All of these worked flawlessly out-of-the-box without any tinkering necessary on Windows XP. All I can say is “give me back XP please!” I don’t care about the O/S. It is entirely incidental, the important thing is the applications that run on top. With a strike-rate of 5 out of 7, I don’t have much hope. Vista has turned my general purpose PC into an internet browsing terminal.

Another gripe: if the security improvements is just User Account Control (UAC) I don’t think that is going to be any benefit at all. I share my PC with an unsophisticated computer user. We use the same limited user account and she has the admin password. For various reasons, it is not possible to change this situation. Just to give an example, I was trying to get MSN Messenger to work for her. After trying several different things – always running as admin, allowing it through the Vista firewall, running in XP compatibility mode, entering a string of commands at the command-line I gave up. She was still keen to get it working, so she googled for Messenger downloads, downloaded them one by one and attempted the install. For each install, UAC popped up the dialog to grant administrator privilleges. Without a pause, she entered the password and clicked through the dialog, allowing the software she had downloaded, which could have been laden with any number of trojans or spyware, full access to the system. Software companies have taught users really well to ignore dialogs with their EULAs and whatnot. Oh, Internet Explorer has stopped working too, perhaps because of one of the attempted solutions to Messenger, so it is fortunate I installed Firefox or the PC would be a paperweight rather than a kiosk.

So basically what I’m saying is, I hate Vista.

Read Full Post »

Threading in MzScheme

This week I have been playing around with threading in MzScheme… I like it!

(thread (lambda () …))

is enough to create a thread and start it running.

You can use channels to pass data between threads safely with (make-channel), (channel-get <channel>) and (channel-put <channel> <data>).

Just to prove you can write Java in any language… say I wanted to have a connection manager. The API is pretty simple – I want to add connections and remove connections. Also, it might be useful to be able to start and stop the connection manager and display the number of connections. There are a number of ways I could implement this, e.g. have a global variable and synchronise access to put and get connections. Alternatively, I could have a thread that looks after connections and send messages to that thread via a channel. Just for fun, let me choose the second option.

The functionality is encapsulated and available through the following API.

(connection-manager-start)
(connection-manager-stop)
(connection-manager-clear-connections)
(connection-manager-show-connections)
(connection-add <input-port> <output-port>)
(connection-remove <input-port>)

If this was production code, I should put the code in a module and only make the above functions available using (provide…). Outside a module, we can of course by-pass the API and put messages in the channel directly.

;; Support function LOG

(define (pad n) (substring (number->string (+ n 100)) 1 3))

(define (now)
  (let* ((date (seconds->date (current-seconds)))
         (secs (date-second date))
         (mins (date-minute date))
         (hour (date-hour date)))
    (format "~a:~a:~a" (pad hour) (pad mins) (pad secs))))

(define (LOG . args)
  (printf "[ ~a ] : " (now))
  (for-each display args)
  (newline)
  (flush-output))

;; First of all, we define a struct for the connection which has
;; an input and an output port

(define-struct connection (input output))

;; Globals for the channel, and the thread - it is a singleton obviously

(define *connections-channel* (make-channel))
(define *connection-manager-thread* #f)

;; The actual manager function
;;   this constantly loops and accepts messages via *connections-channel*
;;   possible messages are:
;;     'stop, 'add-connection, 'remove-connection,
;;     'show-connection, 'clear-connections

(define (connection-manager)
  (letrec
      ((show-command
        (lambda (command)
          (LOG "Received command [" (symbol->string command) "]")))

       (show-connections
        (lambda (connections)
          (let* ((num (length connections))
                 (plural (not (= num 1))))
            (LOG "There "
                 (if plural "are " "is ")
                 num
                 " connection"
                 (if plural "s" "")))))

       (loop
        (lambda (connections)
          (let* ((command (channel-get *connections-channel*))
                 (head (car command)))
            (cond
             ((eq? head 'stop)
              (LOG "Connection manager stopping..."))
             ((eq? head 'add-connection)
              (loop (cons (cadr command) connections)))
             ((eq? head 'remove-connection)
              (let ((c (cadr command)))
                (LOG "Removing connection [" c "]")
                (loop (remove (lambda (e) (eqv? (connection-input e) c))
                              connections))))
             ((eq? head 'show-connections)
              (show-connections connections)
              (loop connections))
             ((eq? head 'clear-connections)
              (loop '()))
             (else
              (LOG "Error: unrecognised-command [" head "]")
              (loop connections)))))))

    (LOG "Connection manager starting...")
    (loop '())))

;; connection-manager-running? checks if the connection-manager
;; is currently running - it is a belt and braces effort

(define (connection-manager-running?)
  (and (thread? *connection-manager-thread*)
       (thread-running? *connection-manager-thread*)))

;; We always check if the connection-manager is running before
;; trying to send a message as (channel-put ...) waits until there
;; is a corresponding (channel-get ...) on another thread.  When
;; testing at the REPL, this can cause problems.  We could use an
;; asynch stream which wouldn't have this problem but I prefer
;; the explicit check

(define (connection-manager-send-message message)
  (if (connection-manager-running?)
      (channel-put *connections-channel* message)
      (begin
        (LOG "WARN - Connection manager is not currently running")
        #f)))

;; The actual API functions.  Most of these simply check if the
;; connection manager is running, and if so, put the appropriate
;; message in the channel.

(define (connection-manager-start)
  (if (connection-manager-running?)
      (LOG "WARN - The connection manager is already running")
      (set! *connection-manager-thread* (thread connection-manager))))

(define (connection-manager-stop)
  (connection-manager-send-message (list 'stop))
  (set! *connection-manager-thread* #f))

(define (connection-manager-clear-connections)
  (connection-manager-send-message (list 'clear-connections)))

(define (connection-manager-show-connections)
  (connection-manager-send-message (list 'show-connections)))

(define (connection-add input-port output-port)
  (connection-manager-send-message
   (list 'add-connection (make-connection input-port output-port))))

(define (connection-remove input-port)
  (connection-manager-send-message (list 'remove-connection input-port)))

;;; Connection Manager Test

;; The test...

(define (test-connection-manager)
  (connection-manager-start)
  (connection-manager-clear-connections)
  (connection-manager-show-connections)
  (connection-add 1 2)
  (connection-manager-show-connections)
  (connection-remove 1)
  (connection-manager-show-connections)

  (time
   (begin
     (do ((i 0 (+ i 1)))
         ((= i 100000) #t)
       (connection-add 1 2))
     (connection-manager-show-connections)))

  (connection-manager-stop))

;; (test-connection-manager)

Read Full Post »

Is Squeak Smalltalk Slow?

This is a question I’m currently interested in knowing the answer to. I don’t know much about Smalltalk or Squeak unfortunately, but from what I do know, it seems like a good fit for the latest idea I have. The primary advantage over other environments I know, is that the image is available at all times. If an image receives a message it can’t handle because of a programming error, it can enter the debugger and wait for me to come along and debug it. I think that a decent Common Lisp implementation will offer me similar functionality.

Unfortunately, playing around with a new language for a couple of days gives a very limited idea of what it will be like to use it to develop a medium-sized application. For me, during the initial stage of investigation, it is very important to know whether it is worth taking the time with very quickly so that as little time is wasted as possible. Unfortunately, Squeak is a little harder to get to grips with than most languages I am familiar with as it is necessary to learn the IDE at the same time as the language. It is not possible (as far as I know) to simply enter a hello world program into a textfile and execute it.

The first script I entered into the Workspace (which is kind of a scratchpad for exploring new ideas) displayed the numbers from 1 to 200 on to the transcript, which is a kind of logging window. Here is the code to do that along with a timing method. If you highlight thecode and select “print it” from the menu, it tells you how long it took to run.

Time millisecondsToRun: [1 to: 200 do: [:i | Transcript show: i ; cr]]

This was the response: 10335

Ouch! 10 seconds. This is by far the worst performance I’ve ever seen in any language including BBC BASIC on a 2MHz machine. I was certain I must be doing something wrong so I asked on the Squeak beginners list. Unfortunately, it seems that it really is that slow. No-one has made any effort to tune the performance. Here is the comment from the Transcripter class:

"Transcripter is a dog-simple scrolling stream with display.  It is intended to operate with no
support from MVC or color in a minimal, or headless version of Squeak.  No attention has been
paid to appearance or performance."

Okay. Well that is a pity – it is one of the first parts of the Squeak people will see and I would have thought that it would put a few people off. Anyway, the “everything is an image” is still selling me so I try to see how long it takes to write 10,000 numbers to a file.

| myFile ios |
ios := ReadWriteStream on: ''.

Transcript show: 'Populate Buffer: ',
        (Time millisecondsToRun: [
                1 to: 10000 do: [
                        :i | ios nextPutAll: ((i asString) , String crlf)
                        ]]) asString , ' millseconds' ; cr.

MessageTally spyOn: [
 	1 to: 10000 do: [
 		:i | ios nextPutAll: ((i asString) , String crlf)]].

Transcript show: 'Position: ', (ios position) asString ; cr.

myFile := StandardFileStream fileNamed: 'c:/test.txt'.

Transcript show: 'Output Buffer: ',
                    (Time millisecondsToRun: [
        myFile nextPutAll: (ios contents)]) asString,
     ' milliseconds' ; cr.

myFile close.

The MessageTally spyOn: is a nice profiler to see where it is spending its time – it is not really part of the initial test.

This produced the following output on the Transcript:

Populate Buffer: 275 millseconds
Position: 58894
Output Buffer: 9 milliseconds

Hmmm… is 275 milliseconds good or bad? I wrote a quick perl script and ran it with Cygwin.

use strict;open (FH, "> t3.txt") || die "Error: Can't write to file";
 for (my $i = 0; $i < 10000; ++$i) {
     print FH "$irn";
 }
 close FH;

It ran in 0.061s – more than 4 times faster than the Squeak. Well, this is not very good at all. MzScheme and Chicken Scheme both produced results similar to the Perl. Asking on the mailing list again, it seems that the integer to string conversion is implemented in Squeak for flexibility whereas [it is suspected that] all the other languages use C libraries.

Now, I’m not the sort of person who is in favour of premature optimisation, but if all the primitives are 4 times slower than Perl for reasons of flexibility that seems like a huge performance hit. It seems like it is harder to drop into C from Squeak than it would be from other scripting languages and Perl speed is about as slow as I like to go normally anyway. Maybe further investigation would reveal that the Transcript and integer to string comparisons are unusually slow. However, I have to balance the time spent investigating new programming languages is time I’m not spending developing my application.

Read Full Post »

Follow

Get every new post delivered to your Inbox.