Wednesday, July 30, 2008

"Who gives a shit?" attitude -> better mental performance

This article was a big surprise to me. The gist is that using the executive function of your brain (switching from deliberation to implementation - making and acting on decisions) has a strong negative impact on all sorts of mental activities.
For example, deciding whether to have cake or cornflakes for breakfast could be enough to make you perform poorly at an interview later on.

A further implication of this (to me) is that people who coast through much of the day like zombies (especially in the morning), not making many decisions, are much better able to perform when they need to, because they haven't depleted those resources yet.

The moral of the story: if you want to improve your overall mental performance, get into the habit of saying "who gives a shit?" about irrelevant decisions like where to put the furniture or whether the curtains need to be washed again this week. Don't deliberate over mundane issues. Don't waste your energy. Just pick the first reasonable option. I'd like to know if strategies like this can minimise this effect, or if we really have to go around like cattle - I know I do, most of the time... Is that what girlfriends are for? To decide where the couch and TV should be and what washing powder to use, so that I can reserve my brain power selfishly for 'clever' use later (which rarely happens)? Seems a little unfair, really...

I have more questions. How do we recover from the effects? How long does it take? Can we speed it up? What about meditation, or induced alpha/theta/delta brainwaves (i.e. by listening to binaural beats, say)? Why does it happen?

Enough rambling (I guess...), I'm off to dodge some decisions! Probably.

Wednesday, July 23, 2008

(Auto-)Growing Panes

In another Swing-related weirdness note, it seems that a certain combination of apparently logical options regarding GridBagConstraints and a JTextArea will cause the JTextArea and enclosing JPanel to expand horizontally by gridBagContraints.ipadx pixels per step, forever.

After scratching my chin in confusion, I whittled out the following minimalish example that demonstrates the result:

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

public class TextAreaExample {
public JPanel createContentPane() {

JPanel contentPane = new JPanel();

JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
// ipadx > 0 causes textarea panel to grow horizontally forever if linewrap is set!
c.ipadx = 1;

JPanel leftPanel = new JPanel();
leftPanel.add(new JLabel("Left"));
mainPanel.add(leftPanel, c);

JPanel logPanel = new JPanel();
logPanel.setLayout(new BoxLayout(logPanel, BoxLayout.PAGE_AXIS));

JLabel label = new JLabel("Hello");
logPanel.add(label);

// create misbehaving textarea
JTextArea log = new JTextArea(10, 40);
log.setLineWrap(true);
log.setBorder(new LineBorder(Color.BLUE));
logPanel.add(log);

mainPanel.add(logPanel, c);

JPanel rightPanel = new JPanel();
rightPanel.add(new JLabel("Right"));
mainPanel.add(rightPanel, c);

contentPane.add(mainPanel);
return contentPane;
}

private static void createAndShowGUI() {
JFrame frame = new JFrame("JTextArea growth test");

TextAreaExample demo = new TextAreaExample();
frame.setContentPane(demo.createContentPane());

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}


I can get around it by setting a preferred size on the JTextArea (a size of 0,0 seems to do the trick without changing the initial layout), but what the hell?

Monday, July 21, 2008

Swing and a miss

Does this method Javadoc from the Swing API confuse you? It confuses me:
/**
* Sets the the vertical alignment.
*
* @param alignmentX the new vertical alignment
* @see #getAlignmentX
* @beaninfo
* description: The preferred horizontal alignment of the component.
*/
public void setAlignmentX(float alignmentX) {


As you can see, the method description and param seem to conflict directly with the beaninfo description. I was sure the first two are a typo, copied from the alignmentY equivalent, but let's have a look at setAlignmentY:
/**
* Sets the the horizontal alignment.
*
* @param alignmentY the new horizontal alignment
* @see #getAlignmentY
* @beaninfo
* description: The preferred vertical alignment of the component.
*/
public void setAlignmentY(float alignmentY) {


???

Also, using it is confusing and the docs don't seem very helpful. I created a JPanel using a vertical BoxLayout, so that as you .add(component)s they stack up beneath each other.
To the empty box panel I added a JLabel with the text "Log" and beneath that, a JTextArea which would hold the log output.

However, I noticed on running the program that the label was not left-aligned - instead, it was indented by about 40 pixels beyond the log textarea beneath. Worse still, when text appeared inside the JTextArea, the label above would jump horizontally right, bizarrely. So the most logical thing to do seemed to be to call label.setAlignmentX(Component.LEFT_ALIGNMENT) to keep the label aligned to the left side of its containing box.
Seemed to be the logical thing to do. But no, this caused no obvious change. Various combinations of this did nothing, until I made the same call on the textarea underneath.

So if you have a vertical box containing a label with a textarea underneath it and you want the LABEL to be left-aligned, you have to tell the TEXTAREA to left-align itself.

...WHAT?

Wednesday, July 09, 2008

The great antivirus scandal of 2008

This report is pretty scary. It's understandable that everybody overlooks the fact that virus scanners can be vulnerable, especially when they're built with lots of 3rd-party plugins (e.g. upx/zip/arj/rar/etc unpackers).

But the fact is, you can become automatically infected by a virus without running the infected program/trojan yourself; the virus scanner scans it automatically, but the file is designed to exploit a vulnerability in your virus scanner and you become infected.
That's a lot more dangerous than having no AV software and just being careful which programs you run...

Symantec is among the worst here, with about 32 vulnerabilities listed compared to 6 or 7 in FProt, AVG and BitDefender.
Personally, I think it serves AV vendors right for coding their products in languages as dangerous as C and C++, which are so vulnerable to buffer overflow mistakes. And nobody can code without mistakes. And the frequency of mistakes increases with code size, of course. They should have written their scanners/plugins in a better programming language (e.g. Lisp).

Tuesday, July 01, 2008

Update on Gambit-C Scheme benchmarks

Thanks to some helpful comments from a few people on my previous post about Gambit-C Scheme, I rebuilt and ran (with a larger minimum heap size specified) those few benchmarks I was bothered pulling off their site and the shootout site for SBCL (which is a very fast Common Lisp implementation I'm interested in using as a kind of reference).

The results in general are much better:

time ./fannkuch -:m20000 11 > output_fannkuch

real 0m9.931s
user 0m9.465s
sys 0m0.172s

time ./fasta -:m20000 25000000 > output_fasta

real 0m29.843s
user 0m25.220s
sys 0m2.700s

time ./binary-trees -:m20000 16 > output-binary-trees

real 0m2.770s
user 0m2.581s
sys 0m0.089s

time ./pidigits -:m20000 2500 > output
real 0m3.322s
user 0m3.093s
sys 0m0.110s


A range of improvement is apparent, with binary-trees benefitting a lot and pidigits not really getting much better.
I picked a 20 meg heap because a) it seems wasteful for individual programs to reserve (and probably waste) huge chunks of memory, if you're running a lot of programs b) when I tried higher values up to 50 megs on the fasta benchmark, it was faster, but only by another .2 seconds or so; about 1-2%... and c) Most other languages, and in this case SBCL, don't seem to request more than about 20 megs for their initial heap size either.

Of note is the fact that the prebuilt version produced slightly faster code than the version I compiled myself, specifying the optimisations mentioned in the INSTALL.txt document. Not sure why... These numbers are for the Gambit I compiled myself, and I didn't feel like dumping it and re-installing the prebuilt version just yet.

Anyway, these are nice results!

Sunday, June 29, 2008

How fast is Scheme? Well....

Thinking that it'd be a good idea to become familiar with Scheme as well as Common Lisp (but, er... probably after I've read Practical Common Lisp and amn't mentally overloaded, what with me being mental so busy and needing to focus my efforts in a more single-threaded manner), I checked out Gambit Scheme in the hopes that it'd produce faster code than the other free Scheme implementations.
I don't know much about Scheme (or Lisp at all really; I've only become interested in it during the last month or so) but it seems that the Scheme compilers produce quite sluggish code, at least looking through the grainy, distorted lens that is the Computer Language Benchmarks Game.

From some of the microbenchmarks published by the Gambit guy(s) on their homepage, it looks as if it fares really well against the Chicken and Mzscheme compilers, but I wanted to examine its performance on problems relative to SBCL, which is the Common Lisp compiler I've arbitrarily chosen.
Since it's not featured on the language shootout, I pulled the SBCL code for a few tests there as well as the Gambit code which was already prepared on their site (why hasn't Gambit appeared on the shootout site for the nosy hackers who want to find out if less mainstream (man I hate that word) languages are ridiculously slow? Many of them aren't! And they're more expressive and comfortable than C++/Java, use them!) and ran a few comparisons.
SBCL comes out very much on top; in general the Gambit programs take two or three times as long to do their job (although I haven't looked at memory usage). But as far as Scheme compilers go, Gambit seems to be improving things.

(Really dodgy) timings on my Macbook (input values = whatever's on the shootout site):

Gambit:
pidigits
real 0m3.611s
user 0m3.508s
sys 0m0.066s

binary-trees
real 0m7.519s
user 0m7.309s
sys 0m0.130s

fannkuch
real 0m12.571s
user 0m12.089s
sys 0m0.205s

fasta
real 0m46.334s
user 0m42.284s
sys 0m2.668s

Lisp SBCL:
pidigits
real 0m2.422s
user 0m2.018s
sys 0m0.308s

binary-trees
real 0m1.899s
user 0m1.723s
sys 0m0.127s

fannkuch
real 0m6.221s
user 0m5.982s
sys 0m0.098s

fasta
real 0m20.730s
user 0m15.267s
sys 0m4.375s

(ratio-pidigits: 1.5
ratio-binary-trees: 3.959
ratio-fannkuch: 2.021
ratio-fasta: 2.235)


One thing I've noticed from these coarse measurements is the "sys" component of the execution time is mostly higher for SBCL; maybe this means a lot of allocation and de-allocation of stuff is going on ...Or something.

Extra legs on a dog

This hi-larious entry on the wikiwikiweb offers a series of biological analogies for the origins of some popular/not-so-popular programming languages, on the premise "how other languages became ObjectOriented octopi".

I particularly like:

JavaLanguage
  • ..made by taking an 8-legged dog, housebreaking it, and tearing out its skeleton. Then giving it a machine shop.

    • a boneless 8-legged dog manages to be less useful than either an octopus or a dog - but it comes with a machine shop, so that's good.

That said, this is exactly the kind of thing that I would chuckle ceaselessly at, for which even fellow coders would shun me for being lame and non computer scientists would simply presume me to be insane. Fair play, really.

Tuesday, June 24, 2008

Lisp problem 10: RLE of a list

This one worked out much easier, but again, I went at it non-recursively. Bitching about my struggles with the previous problems made me realise that I had solved most of the previous problems recursively but non-tail-recursively.
I guess there's a danger there of writing really poorly-performing functions on the assumption that the compiler will optimise them. Actually, I don't even know if SBCL does tail-call optimisation... It somehow seems easier to express tail-recursive solutions in Haskell, so far anyway - as a complete newbie to both languages.

;; P10: Run-length encoding of a list.
(defun encode (list)
(let ((chunked (pack list)) result)
(dolist (chunk chunked)
(setf result (append result
(list (list (length chunk) (car chunk))))))
result))


Oh yeah, how do you get around doing that ugly (append result (list (list x y))) stuff? I assume that's super slow, unless Lisp lists have a pointer to the last element for quick access since (you'd think?) appending is common. But then, some of the stuff I read in Practical Common Lisp suggests a push/reverse pattern, which to me seems a bit awkward.

99 lisp problems. Some are hard!

This much publicised set of 99 Lisp problems (taken from an original set of Prolog problems) seems like a nice step for me to take in learning Lisp as a novice to the language.

I figured the first few would be really easy with a smooth learning curve as the questions get more difficult. Certainly, I didn't expect to spend at least two hours screwing up question 9; an ostensibly straightforward problem requiring you to convert a sequence into a list of sublists, grouped by consecutively equal elements (i.e. (1 4 4 8 1 9 1 1 1 2 2 3) -> ((1) (4 4) (8) (1) (9) (1 1 1) (2 2) (3))).

After trying to solve this one a few different ways, I rejected a recursive approach and simply looped through all the elements, doing dirty stuff:
(defun pack (list)
(let (a main-list)
(dolist (x list)
(if (and (not (null a)) (eq x (car (last a))))
(setf a (append a (list x)))
(if (null a)
(setf a (list x))
(progn (setf main-list (append main-list (list a)))
(setf a (list x))))))
(setf main-list (append main-list (list a)))
main-list))


I had a quick peek at the solution provided on the site and didn't bother going through it except to note that it was indeed recursive (and not tail-recursive). Partly because some of the identifier names are in Portuguese and partly because it looks similar to the mess I had when I tried to do it recursively; I'm just not comfortable with how lists work yet - I was getting stuff like ((1 (1 (2 3)))) and ((1 (1 (2))) . 3) and all sorts of other crap.
I'm sure I could have done this quicker (and much longer and uglier) in Java, but not figuring it out properly in Lisp is making me feel a bit stupid. Wah.

Friday, May 23, 2008

From I Ran to Eye Rack

In a thread on codeproject, someone humorously commented that "pedophile" must mean somebody with a foot-fetish: American pronunciation has even changed it from "peed-o-file" to "peddo-file", which is almost equivalent to "encyclo-peddy-ah" (since American spelling similarly converts that 'ae' glyph to an 'e').

Another funny dodgy American pronunciation is the popular "eye-raq / eye-ran" thing. It was entertaining to hear that our ex-Taoiseach Bertie Ahern was introduced as "Bertie Ay-hern" by Nanci Pelosi on a recent trip to the US.
As culturally-prevalent-and-nobody-corrects-themselves pronunciation errors go, it seems as bad as the Japanese 'l'->'r' transliteration (take the eravator to the rower reveru, prease), since at least Japanese have the excuse that the 'l' sound doesn't appear in their language and they thus have trouble pronouncing it.

Tuesday, May 06, 2008

gymnastic bounces, late

Received 3/5/2008 (happy birthday):

Your membership in the mailing list Announce-gymnast has been disabled due to excessive bounces The last bounce received from you was dated 29-Dec-2003. You will not get any more messages from this list until you re-enable your membership. You will receive 2 more reminders like this before your membership in the list is deleted.

Excessive bounces, but the last one my account apparently sent was four and a half years ago? I don't think I even subscribed myself to that list, though I was in the gymnastics club in first year of college. Weird.

Friday, April 11, 2008

Java's arithmetic operators

Here's a weird little one that confused me at first:

 @Test
public void testWeirdArithmeticOperators() {
double a = 1.0 / + + + 2.0;
assertTrue(0.5 == a);
String s = + + + + 0 + "abc" + "def";
assertEquals("0abcdef", s);
}


After playing about for a bit, switching some +es to -es and vice versa, I realised that the effect is that each + or - symbol could be rewritten as follows:
+ -> (+1)*
- -> (-1)*

So that the expression "+ + + 2.0" becomes "(+1) * (+1) * (+1) * 2.0" = 2.0, and the expression "- + + 2.0" becomes "-1 * +1 * +1 * 2.0" = -2.0. Thus, the sign of the result is negative for an odd number of - symbols and positive for an even number.

Seems a little pointless, but I suppose the logical way to see it is:
- + - x = - (+ - x) = - (+ (-x)). It makes sense then that the parser would accept it, but in it that form it looks wrong to (my) human eye.

Also, in writing this post I noticed that JUnit's assertEquals doesn't really like doubles:
assertEquals(0.5, 0) passes, as does assertEquals(Double.valueOf(0.5), Double.valueOf(0.0)) and other combinations. That's why I needed to use assertTrue(...) and == above. Huh.

Tuesday, April 01, 2008

the poor man's breakpoint

Since Eclipse is kind of very ridiculously slow betimes, I tend to avoid making it do too much work, for fear of it getting stuck in a rut and slowing down. Partly because my work machine is pretty much a doorstop, for the purposes of working with Eclipse (512mb RAM just doesn't cut it, if you want a browser and other apps open at the same time - I had to stop using the latest Opera snapshots while coding, as they use too much RAM at the moment, compared to Firefox 3.0b4).

So instead of running tests/etc in the debug perspective and adding breakpoints where I want to stop (if that block of code is executed), I've taken to doing things like this instead:
throw new RuntimeException("FUCK");
This means I get a stack trace showing how we got to the current state, which is often enough to realise what the problem is (at least, it was just now; I saw that a method I didn't expect to be called was being called by a parser for poorly-formed XML messages. Until that point, I didn't realise the messages were now poorly-formed as they weren't before I swapped XMLSerializer for LSSerializer earlier today).
Also, it's easy to search and remove your debugging throws afterward, since they contain the reasonably memorable, short string "FUCK". Of course, you wouldn't want to forget about it and leave one in a currently unused (as far as you know) method, lest an end-user find that their application is throwing an exception because FUCK. :)

Perhaps a more subtle keyword could be selected (how about "Fire in the hole" or "Get to the choppa!")...

Friday, March 28, 2008

how... odd

Here's a funny random thing. Residents in some countries can apply for an Irish visa online.

They're even nice enough to provide translations of the "Information on completing Online Application" into other languages, including Chinese. However, in their list of countries for which they allow online visa applications, China is not present.

So why the hell did they bother translating the "how to use the online application system" PDF into Chinese...?

Welcome to the Irish government. Home of weird bureaucracy and silly contradictions.

Also, the actual web application tells Opera users to upgrade their browser because of some buggy cookie test. As usual, an Irish government site/webapp ends up poorly designed and coded, and probably cost at least €10M. Saps.

Monday, March 24, 2008

Freeze! squad

Here's one of the things I really like about Mandarin Chinese - its simple straightforwardness; a lack of needless obfuscation. The Chinese phrase "别动!" (bie2 dong4) usually means "Don't move!". The character "队" (dui4) means a squad or team.

Combined, the resulting term "别动队" means "special ops team". Literally, "don't move squad".

:)

Thursday, March 20, 2008

When is a clone not a clone? When it's half a clone!

After finding that the clone of a two-dimensional array in Java seems to not be a clone, I searched the web, already strongly suspecting the outcome.

Behold (from one of Sun's references):
A clone of a multidimensional array is shallow, which is to say that it creates only a single new array. Subarrays are shared.
Then that's hardly a clone now is it? Damn you AvatarJava. Daaammmnnnnn youuuu!

Wednesday, March 19, 2008

我找到了书!

I ordered a Wacom Bamboo One graphics tablet from dabs.ie about two weeks ago, and am pretty impressed by it (once I installed the updated drivers for my Macbook, since it was sucking with multiple users/sleep/USB disconnect+reconnects). It's nice for scribbling and drawing, even if it just makes me realise what a poor graphic artist I am. The main reason I bought it was for studying Chinese - up to now, I'd been using a scheduled revision program (first Pauker, then Mnemosyne, then when it wouldn't build on OS X Leopard due to one of its Python dependencies being a bit outdated, Anki) to learn Chinese characters and sentences, and writing the characters vertically on paper as I revised them. However, to avoid spoiling the recall process, I was having to draw gridlines and cover up already-drawn characters so I wouldn't see them when presented with flashcards for review. There two problems there; one was that lots of paper was being used up needlessly, and two was that it was fiddly and a hassle, so I stopped doing it due to my self-discipline not overcoming the coefficient of resistance (my laziness is a rough cloth).

Since the graphics tablet arrived, I started using it to sketch the characters in Seashore, a simple bitmap drawing program.


Then I check if I was correct (if not, I draw each character four times or so), clear the canvas (by hitting backspace) and grade myself in Anki, moving onto the next item. It's faster and easier, two reasons which have helped me keep doing it. Along with some truly inspiring ideas (the "how many things will I definitely do tomorrow" game and the "I'll just get the file out" trick) I read on Mark Forster's site, which you should incidentally go and read now, by the way, since it might just help you change your life for the better.

Tuesday, March 11, 2008

Newsflash: Eclipse is bloody slow

It's probably not news to anyone who has ever used Eclipse, and I've been aware of the fact since I started working with Eclipse as my IDE in 2006. However, right now, on this admittedly rubbish machine (PIII 1ghz, half a gig RAM, running Opera as well with a million tabs open which takes up 80-100 megs), it took about 90 seconds to get from clicking the "Find and install..." menu option in "Help->Software updates" to displaying the "Install/Update" dialogue box. It doesn't seem necessary to do a lot of work to get there, since that dialogue simply contains a radio button choice between updating currently installed features and looking for new ones.
What's going on here? I know Java can be slow and Eclipse uses a fair bit of memory so I'm probably swapping to disk like a king, but it still seems excessive.

Friday, March 07, 2008

more on profiling

Well, after being forced to go down the manual speed profiling route, I'm pretty happy about the results. Manually inserting timing code around loops of single (if possible) calls is nice because you can focus your search in a reasonably directed, intelligent way. Since giving up on Eclipse's TPTP profiler yesterday evening, I was able to optimise various parts of the code so that the main client/server conversation executes five or six times faster than previously. Most of the optimisations were of the "cache objects instead of constantly recreating them locally" variety, which can introduce errors (which is always a risk when adding more state to your code, but hey, welcome to one of the downsides of OO) but can also improve performance drastically.

I'm hoping I can find more higher-level optimisations over the next while, but I've gotta draw a line now and get back to adding functionality, or I'll look like quite the sap when I have to demo the current stuff to my pals.

Thursday, March 06, 2008

Eclipse, TPTP and accursed JVMTI

I had Eclipse's update manager automatically "upgrade" some of the component versions, including the TTPT tools I was using to try to profile some VERY SLOW code I'm working on, and since then (and following multiple restarts of Eclipse and a reboot), I cannot profile any Java code.
Hitting the "Test availability" button for the post-1.5 JRE data collectors freezes Eclipse for about 10 seconds before popping up an alert box which states "The JVMTI agent org.eclipse.tptp.jvmti is not available", with a "Show details" button which expands the dialogue to display a completely blank textbox. This is clearly bollox. Searching the web leads to forum posts advising to meddle with the "Agent Controller" and RAServer programs, but I can't find them and never needed to before.

What Eclipse needs is a lightweight, simple profiler which doesn't run into stupid problems like this. For fuck's sake, I've spent over an hour getting nowhere with this stuff. Of course this would happen now, when I'm expected to give a demo of the code (running faster than what it replaces) on Monday morning.

Results of "Test Availability":


Trying to run the profiler:


An automatic update should not break Eclipse's profiler completely. Now I've gotta go with the good old "manually insert time measurement code all over the shop" technique, which fairly sucks.