Monday, June 15, 2009
Friday, June 12, 2009
Tuesday, June 9, 2009
Hackjob in production
I just noticed this snippet from the Yahoo SEM code:
<SCRIPT language="JavaScript" type="text/javascript">
<!-- Yahoo! Inc.
window.ysm_customData = new Object();
window.ysm_customData.conversion = "transId=,currency=,amount=";
var ysm_accountid = "ABCDEF123456";
document.write("<SCR" + "IPT language='JavaScript' type='text/javascript' "
+ "SRC=//" + "srv1.wa.marketingsolutions.yahoo.com" + "/script/ScriptServlet" + "?aid=" + ysm_accountid
+ "></SCR" + "IPT>");
// -->
</SCRIPT>
This code is given to webmasters for both secure and non-secure URLs. Compare it to the Google analytics loading snippet:
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
Yes, Yahoo provides code that requests a URL with no protocol (src=//srv1.wa.marketingsolutions.yahoo.com). Talk about funky code.
Wednesday, June 3, 2009
Haibane Renmei
I watched Haibane Renmei a few days ago. I can't really tell yet if this is going to be the case, since my gut feel has a natural bias towards things I've seen more recently, but it may well become of my favorite animes.
I think there are a lot of fresh concepts and I find the slice-of-life feel of the series very immersive. There are many unanswered questions left for interpretation: the characters' origins, the geography, the rules, all contribute to provide a rich culture to the series' world. Exploring the mysteries unravels interesting theories that can add depth to the world on their own.
It's all very fascinating and stimulating. It's not very often that a series makes me pick up creative writing again. :)
Thursday, May 28, 2009
Does it matter if immutable data is slow?
Note: this post is specifically about Java.
One thing I noticed about the benchmarks in the blog post I linked to on my last post is that the Java tests weren't wrapped in synchronized blocks (which would be a given in any concurrent program).
So I decided to modify it a bit and see how things went. Here's the code:
public final class Bench {
public static Object mutex = new Object();
public static Object getMutex() {
return mutex;
}
//immutable
private static final class Person0 {
public final String name;
public final int age;
public final double balance;
public Person0(final String name, final int age, final double balance) {
this.name = name;
this.age = age;
this.balance = balance;
}
}
//idiomatic mutable
private static final class Person1 {
private String name;
private int age;
private double balance;
public Person1(final String name, final int age, final double balance) {
this.name = name;
this.age = age;
this.balance = balance;
}
public void setName(final String n) {
this.name = n;
}
public void setAge(final int n) {
this.age = n;
}
public int getAge() {
return this.age;
}
public void deposit(final double n) {
this.balance += n;
}
}
//mutable w/ public fields
private static final class Person2 {
public String name;
public int age;
private double balance;
public Person2(final String name, final int age, final double balance) {
this.name = name;
this.age = age;
this.balance = balance;
}
public void deposit(final double n) {
this.balance += n;
}
}
private interface Test {
double test(int iters);
}
private static final Test TEST0 = new Test() {
public double test(int iters) {
Person0 person = new Person0("John Doe", 19, 100.0);
for (int i = 0; i != iters; i++) {
synchronized (mutex) {
person = new Person0(person.name, person.age + i, person.balance + 1.0);
}
}
return person.balance;
}
};
private static final Test TEST1 = new Test() {
public double test(int iters) {
Person0 person = new Person0("John Doe", 19, 100.0);
Person0 p;
for (int i = 0; i != iters; i++) {
p = new Person0(person.name, person.age + i, person.balance + 1.0);
synchronized (mutex) {
person = p;
}
}
return person.balance;
}
};
private static final Test TEST2 = new Test() {
public double test(int iters) {
Person1 person = new Person1("John Doe", 19, 100.0);
for (int i = 0; i != iters; i++) {
synchronized (getMutex()) {
person.setName("John Doe");
person.setAge(person.getAge() + i);
person.deposit(1.0);
}
}
return person.balance;
}
};
private static final Test TEST3 = new Test() {
public double test(int iters) {
Person1 person = new Person1("John Doe", 19, 100.0);
for (int i = 0; i != iters; i++) {
synchronized (mutex) {
person.name = "John Doe";
person.age += i;
person.deposit(1.0);
}
}
return person.balance;
}
};
private static final Test TEST4 = new Test() {
public double test(int iters) {
Person0 person = new Person0("John Doe", 19, 100.0);
for (int i = 0; i != iters; i++) {
person = new Person0(person.name, person.age + i, person.balance + 1.0);
}
return person.balance;
}
};
private static final Test TEST5 = new Test() {
public double test(int iters) {
Person1 person = new Person1("John Doe", 19, 100.0);
for (int i = 0; i != iters; i++) {
person.name = "John Doe";
person.age += i;
person.deposit(1.0);
}
return person.balance;
}
};
private static double test(int times, Test test, int iters) {
long best = Long.MAX_VALUE;
double balance;
for (int i = 0; i != times; i++) {
long now = System.currentTimeMillis();
balance = test.test(iters);
now = System.currentTimeMillis() - now;
if (best > now) best = now;
}
return (double) iters / ((double) best / 1000.0);
}
public static void main(String[] args) {
final int iters = 10000000;
System.out.printf("Immutable sync all: %f updates/s\n", test(5, TEST0, iters));
System.out.printf("Immutable sync =: %f updates/s\n", test(5, TEST1, iters));
System.out.printf("Mutable idiomatic: %f updates/s\n", test(5, TEST2, iters));
System.out.printf("Mutable fields: %f updates/s\n", test(5, TEST3, iters));
System.out.printf("Unsafe immutable: %f updates/s\n", test(5, TEST4, iters));
System.out.printf("Unsafe mutable: %f updates/s\n", test(5, TEST5, iters));
}
}
And the results:
| Immutable syncing constructor | 14,903,129 updates/s |
| Immutable syncing assignment | 14,880,952 updates/s |
| Mutable with idiomatic Java | 18,832,391 updates/s |
| Mutable accessing fields directly | 18,832,391 updates/s |
| Non-synced immutable | 70,921,985 updates/s |
| Non-synced mutable | 322,580,645 updates/s |
Interesting points to note:
- Immutables turn out to be slightly faster than mutables when synchronization is involved.
- Using idiomatic set/get methods directly seems to be about as fast as accessing fields directly (albeit more verbose).
- Non-thread-safe code runs about an order of magnitude faster than the synchronized counterparts. Does that mean I need 20+ CPUs to match the speed of a single-threaded program (due to synchronization overhead)?
So is concurrency really overhyped or did I just do something dumb with the code?
Tuesday, May 26, 2009
Monday, May 25, 2009
Friday, May 22, 2009
Dunning-Kruger and Cobra
I saw Cobra the other day and was curious about what people had to say about it. I noticed that some people are rather quick in pronouncing it "retard", "stupid", and some other not-so-flattering adjectives.
It's pretty disappointing that these people are so quick to take a scornful position when a new language comes along and it happens to be, you know, different. Or, (gasp) similar to stuff that already exists.
I guess I'll have to wait a bit more before I get to see comments from people who have actually used the language.