HNHacker News
TopNewBestAskShowJobs

iam

206 karma · joined January 15, 2011

submissionscomments
iam··on Long hours and zombie-like employees at Gameloft Auckland
A lot of new employees have either relocation or signing bonuses, that would have to be repaid if they left the company within 1-2 years. Compounding this, the bonus is usually given out pre-tax but has to be repaid post-tax.

So sometimes there really isn't an option but to finish the year(s) or take a big financial hit.

iam··on Apple MacBooks Can Be Hacked Through The Battery
Why, oh why, would any laptop run any code from a battery?
iam··on OOP in Bash
Why can't you do polymorphism? It looks like he just needs to add vtables to make that work.
iam··on Mozilla lays out multi-process Firefox engineering goals
What makes you think their code isn't multi-threaded as it is?
iam··on Kivy: python UI framework. GPU accelerated, multi-input (win,osx,lin,android)
This is cool, but to seriously use this one would have to have an idea of how extensible this is (is it easy to add new widgets? reskin existing widgets?) compared to existing UI toolkits.

Also it's entirely unclear what makes Kivy specific to NUI? I am assuming that you ditched the old one widget/one focus model and that multiple widgets can have focus at the same time. But that's not really said anywhere, it just "looks" like it from the multiple scrollbars in the demo.

So really aside from the very cool demo there is no strong evidence to convince someone to switch to Kivy if they've worked with UI toolkits before.

Maybe talk about this over the tech demo on top of having cool music.

iam··on Ray, a Ruby game library
Surprising that there's no physics engine integration like Chipmunk or Box2D.
iam··on Ruby Arduino Development
What's the benefit? Can you leverage any Ruby libraries? Or is it Arduino development with Ruby syntax?
iam··on How much should you pay developers?
Yeah, I had the same problem with that article. I have a friend who has at least 15+ years of programming experience (including paid contracting), but only 3 years out of college working "full time" for a salary.

So that means he's in the 1-5 years bucket automatically? Sorry, but I don't think so, since he can run circles around most 20+ experience people.

There's just no comparison between people like that who do programming in their spare time since they were a kid and people who just started programming in college and only did it for school or their jobs. It's absurd to rank them the same.

iam··on Floating Point Determinism
Still, he brings up a good point. If the source of non-determinism is known to be exactly in the physics engine, maybe it's possible to share the global physics state every once in a while.

I don't know much about game network code, but is this feasible at all? Another post brought up the reason for using lock-step networking is because of "thousands" of units, so I assume the biggest data is the physics data (x,y,z velocity, etc of said units).

If some physics errors could be tolerated for a few ticks, maybe a binary search of the gamespace could be used to figure out where the error came from, and sync up the game state in that area. Could be fairly low bandwidth right?

iam··on Synchronous RTS Engines and a Tale of Desyncs
I think this would essentially amount to having save/load game for multiplayer, and how often have you seen games have one of those?

Still, desync errors are pretty common in early versions of RTS, I remember pulling my hair out while playing Starcraft and getting desynced non-stop. Or maybe it was the cheaters!

iam··on Tenacious C shows you what points to what
Eclipse has very sweet gdb integration, and is probably the best C/C++ IDE for Linux if people can get over the fact that it's written in Java and uses up gigs of ram.

Nothing on Linux beats the C++ parser that Eclipse has (I tried everything and it feels like programming in the stone age unless it knows how to interpret templates and go to def/go to usages works). Heck, even on Windows probably only Visual Studio beats it, thanks to being written in speedier native code and already supporting C++0x intellisense.

It's not as useful for C though since there's plenty of other IDEs that can do macro unfolding and if that's not even needed then just using your favorite text editor + cscope provides a fast way of traversing a call graph.

That being said C/C++ IDEs are still decades behind Java or C#. Where's our dozens of automated refactorings that other languages have?

iam··on Tenacious C shows you what points to what
Toolchain: MinGW, gcc 3.5, gdb 5.2

Yet it only runs on Windows? Thanks, but I do virtually all my C programming on Linux. The only thing Windows is useful for is to cross compile to other targets (it's usually more work to set up Linux to cross compile to a target).

Why anyone would write C on Windows for Windows I have no clue.

iam··on The Broken Promises of MRI/REE/YARV
I think this is a problem that exists across any VM that implements a GC, not just Ruby.

.NET CLR has the exact same problem (perhaps a harder one, since CLR has a moving GC), so anytime they touch GC references (pointers to objects that are collectible) it's always wrapped in an explicit GC stack frame (think GC struct that lives on the stack). Furthermore, all reads/writes are carefully done with macros (which of course expands to volatile + some other stuff) to make sure the compiler doesn't optimize it away.

On the one hand, this is nice because they don't need to scan the C-stack (it scans the VM stack and the fake GC frame stacks -- well it's one stack but you skip the native C frames), on the other hand this means that any time a GC object is used in C code (ok, actually it's C++) they have to be real careful to guard it.

Of course bugs crop up all the time where an object gets collected where it shouldn't have, it happens so often that there is a name for it -- "GC Hole".

Astute readers and users of p/invoke may remark that they don't have to set up any "GC frames" -- that is because this complicated scheme is not exposed outside of the CLR source. Regular users of .NET who want to marshal pointers between native/managed can simply request that a GC reference gets pinned, at which point I'm mostly sure it won't get collected until it's unpinned.

The bad news is I'm almost positive there is nothing you can do with just C here to make this problem go away. You'd want stuff to magically just happen under the hood, and C++ is the right way to go for that.

It's probably possible to create an RAII style C++ GC smart pointer that would be 99% foolproof at the expense of some performance. It gets a little bit trickier if we are doing a moving collector. I am thinking it could ref/unref at creation/destruction, and disallow any direct raw pointer usage not to shoot yourself in the foot.

Of course the people writing the GC still need to worry about this..

iam··on Google just launched prizes.org
Wasn't there an article a few months ago on HN about people completely changing their behavior when rewarded for the same task with money vs praise?
iam··on This is why memory fragmentation is bad
I remember that blog post like it was yesterday. I guess the Mozilla source code is such a gargantuan beast at this point that it really does take years to get significant improvements into it?

Could explain their recent flurries of rewriting the javascript jits.

iam··on This is why memory fragmentation is bad
What's actually surprising is that it took them this many years to get it fixed. Memory fragmentation is just as bad as memory leaks. To the user, the RAM being used just keeps going up and up until they run out of memory and have to restart FF.
iam··on Why Fair Bosses Fall Behind
Interesting link. I took a read of that chapter, and found this paragraph additionally enlightening:

> I say that the conduct of Manlius is more praiseworthy and less perilous for a citizen who lives under the laws of a republic; inasmuch as it operates entirely for the benefit of the state, and can never favor private ambition. For by such conduct a man can never create any partisans for himself; severe towards everybody, and devoted only to the public good, a commander by such means will never gain any particular friends, such as we have called partisans. Thus this course of conduct can only be of the greatest benefit and value in a republic, as it looks only to the public good, and is in no way open to the suspicion of individual usurpation. But with the system of Valerius, quite the contrary is the case; for although it produces the same effects so far as the public service is concerned, yet it is calculated to inspire doubts and mistrust, on account of the special devotion of the soldiers to their chief to which it will give rise, and which might be productive of bad effects against the public liberty, in case of his being continued in command for any length of time.

So Machiavelli is basically saying in the context of a republic, it is better for a commander to rule through terror/harshness (what the article calls power) rather than respect. The reason being is that gaining respect will cause the commander to gain friends (the person commanding via terror will have none/few friends) and make that commander a risk to the state by being a potential tyrant.

Given this, it's not surprising that Machiavelli advocates Manlius over Valerius, since the behavior of Valerius is in the end disadvantageous to everybody else.

However, does this really apply to a company? Most simply aren't run as a republic, but more of a benevolent dictatorship. So even if a if a manager does rise up to be the new CEO (a "tyrant"), it's probably because whoever appoints the CEO (the board?) thought he would make a better CEO than the last guy, so in the end the company is the one that benefits -- not just the individual.

In fact the article later points out (on the second page) that the CEO who ruled through harshness/terror was later kicked out for poor performance. Maybe commanding through respect is better for companies after all?

iam··on Some Apps Do Sell: Developer Makes $750K in 3 Weeks on Android Market
This tells it all. Looks like they were developing it for at least 1 year, I'm guessing they had something to the tune of 4-6 people (if not more) actually working on the development.

Still, if they keep up this revenue for a year, it could end up being some very nice returns. Will they really be selling ~$1m a month, or will it taper off soon?

iam··on A trip through the Graphics Pipeline
Way too much useful information, I could spend hours reading this blog :)
iam··on TinyVM: A lightweight, fast virtual machine in < 500 lines of ANSI C
I was quite curious as to this, so I looked into the code (using GCC 4.4.5 on a 32-bit VM). Switch statements can be optimized in 2 ways (doing a binary search - log n checks/jumps, or doing a jump table, no checks and 2 jumps). Usually the jump table is done for dense cases and binary search for sparse cases.

I will post the disassembly of the code as-is first. Then the same exact code but using a switch statement (change all the if/else into a 'case' and nothing else).

  // loop header (break out of loop if we hit END)
   1a:   8b 04 99                mov    eax,DWORD PTR [ecx+ebx*4]
  1d:   83 f8 ff                cmp    eax,0xffffffff
  20:   0f 84 62 01 00 00       je     188 <run_vm+0x188>
  26:   89 fa                   mov    edx,edi
  // inside of the loop begins here (theres a jmp 28 instruction at the bottom that i omitted here)
  28:   8b 52 0c                mov    edx,DWORD PTR [edx+0xc]
  // now edx == &vm->pProgram->args
  // FAIL: vm->pProgram->args is loop invariant and shouldn't be reloaded every iteration
  // this is either a failure to prove the load was redundant or a failure to allocate this its own register without spilling
  2b:   83 f8 01                cmp    eax,0x1
  // why is this here? instruction scheduling magic probably.
  2e:   8b 14 32                mov    edx,DWORD PTR [edx+esi*1]
  // esi is the instr_idx 
  // new edx is vm->pProgram->args[instr_idx]
  31:   8b 32                   mov    esi,DWORD PTR [edx]
  // esi is arg0     == vm->pProgram->args[instr_idx][0]
  33:   8b 52 04                mov    edx,DWORD PTR [edx+0x4]
  // edx is arg1     == vm->pProgram->args[instr_idx][1]
  36:   89 55 d4                mov    DWORD PTR [ebp-0x2c],edx
  // FAIL: spill vm->pProgram->args[instr_idx] to stack.
  // why is this a fail? it's already on the stack, so we can reconstruct it slightly slower without spilling
  39:   0f 84 01 01 00 00       je     140 <run_vm+0x140>
  // finally the je for the cmp

  // CMP/JE pairs for ELSE IFs follow until end
  3f:   83 f8 02                cmp    eax,0x2
  42:   0f 84 48 01 00 00       je     190 <run_vm+0x190>
  48:   83 f8 03                cmp    eax,0x3
  4b:   0f 84 5f 01 00 00       je     1b0 <run_vm+0x1b0>
  51:   83 f8 04                cmp    eax,0x4
  54:   0f 84 0e 01 00 00       je     168 <run_vm+0x168>
  5a:   83 f8 05                cmp    eax,0x5
  5d:   8d 76 00                lea    esi,[esi+0x0]
  60:   0f 84 12 01 00 00       je     178 <run_vm+0x178>
  66:   83 f8 06                cmp    eax,0x6
  69:   0f 84 61 01 00 00       je     1d0 <run_vm+0x1d0>
  6f:   83 f8 07                cmp    eax,0x7
  72:   0f 84 70 01 00 00       je     1e8 <run_vm+0x1e8>
  78:   83 f8 08                cmp    eax,0x8
eax is the bytecode for the current instruction (vm->pProgram->args[instr_idx]). Notice that the first time it inlines the code (for the MOV instruction). The rest of the time it's a cmp/jcc pair (I omitted the rest of the asm for clarity, but it's cmp/jcc all the way down).

So that alone makes it that a MOV bytecode would get executed almost right away. Then for everything else, PUSH, POP, etc you have to go through a linearly increasing sets of cmp/jcc pairs. So in this case if the probability distribution of your interpreted program meant that most opcodes were MOV, PUSH, POP, you could get pretty good performance. But once it goes through a few cmp/jcc pairs you have lost the performance benefit of using if/else, it will get slower than using a switch.

There are also a few potential fails here (look at my FAIL comments). The value for &vm->pProgram->args gets recalculated every loop iteration, this is probably a register allocation fail (not enough registers on x86). And vm->pProgram->args[instr_idx] gets spilled to stack. That's really annoying and probably unnecessary.

---------

Now let's take a look at the switch statement! I was curious to see if it would generate a binary search table or a jump table. In theory it should be the latter since the opcodes are 0-25 inclusive (with -1 for END, which is actually 0xFFFFFFFF and is not easily a candidate to become a jump table member). x

  //loop header
  1a:   8b 04 99                mov    eax,DWORD PTR [ecx+ebx*4]
  1d:   83 f8 ff                cmp    eax,0xffffffff
  20:   74 48                   je     6a <run_vm+0x6a>
  22:   8d b6 00 00 00 00       lea    esi,[esi+0x0]
  // loop beginning (there's an omitted jmp 28 lower on)
  28:   8b 7e 0c                mov    edi,DWORD PTR [esi+0xc]
  // now edi == &vm->pProgram->args
  // FAIL: vm->pProgram->args is loop invariant and shouldn't be reloaded every iteration
  // this is either a failure to prove the load was redundant or a failure to allocate this its own register without spilling
  2b:   83 f8 19                cmp    eax,0x19
  // compare eax to 25 (JLE)
  // compiler was unable to prove that the instruction is in the range [-1, 25]. this will always cause a >25 check every loop iteration (bad)
  // i wanted to try adding a __builtin_unreachable() as a default switch case to fix this, unfortunately i don't have gcc 4.5
  // also maybe doing a switch on eax & 0x20 so it knows its less than 32, 32 might be small enough to generate 7 blank jump table entries
  2e:   8b 14 17                mov    edx,DWORD PTR [edi+edx*1]
  // new edx is vm->pProgram->args[instr_idx]
  31:   8b 3a                   mov    edi,DWORD PTR [edx]
  // arg0
  33:   8b 52 04                mov    edx,DWORD PTR [edx+0x4]
  // arg1
  36:   89 55 d4                mov    DWORD PTR [ebp-0x2c],edx
  // FAIL: spill vm->pProgram->args[instr_idx] to stack.
  // why is this a fail? we can always get it from [esi+0xc] like at the beginning of the loop
  39:   77 1d                   ja     58 <run_vm+0x58>

  // aha, thats what the cmp eax, 0x19 was for previously.. refer to previous comment
  3b:   ff 24 85 00 00 00 00    jmp    DWORD PTR [eax*4+0x0]

  // jmp table badassery. but why did it take so long to get here?
  // this is a JMP r/m32 (jump near, absolute indirect)
  // the 0x0 gets set to a jump table offset by the linker later (i decompiled the .o file only)

  // the jmp table itself will look like JMP address-back-into-run_vm-as-a-constant

This is basically the same code as before except that: there's an additional cmp/ja instruction pair to check that the instruction code is in the [0,25] range (and of course the jmp to the jmp table instead of the if/else pairs). This makes it always slower for a branch that will never get taken, and ruins the branch prediction of the first few iterations.

Also the indirect jmp does make it a bit harder to do instruction prefetching, but this should be truly straightforward since the value of 'eax' is known for a good 8 instructions from the beginning of the loop (and the prefetching is trivial for the direct jumps). Another consideration is the L1 i-cache, which is 32K on a Nehalem. A quick google search for the micro-ops cache reveals it to be 12K. Since the loop is fairly tiny, both of these easily fit into those caches with probably at least 1 order of magnitude left over.

Supposing that the redundant cmp/ja is removed, we are now on a more even field. It should be faster for pretty much anything except the first case (instruction is a MOV).

  jmp [indirect abs]
  jmp direct abs
vs

  cmp eax, 0x0 // is EAX a mov?
  jg somewhere_else // skip the following section if its not a MOV
The second code will always be faster if we're always hitting MOVs, don't ask me to prove this, but it's a gut feeling that there's less micro ops involved in the second case. The equal point will probably be when the instrucitons are always PUSH (1) or POP (2). But after that it will always be faster. So I think overall unless all the instructions are MOV,PUSH,POP (haha unlikely) the jmp table solution should be faster with cmp/ja removed.

That being said, I think I've spent too much time on this as-is and will not be trying to remove the cmp/ja.

-----------

Summary: GCC doesn't generate the best code, and there's some things that are hard for even the compiler to optimize. Sometimes you have to massage the compiler into doing what you want, and it doesn't mean the theoretical approach to using switches over chained if/elses is flawed.

It's my gut feeling that if we can get the optimizer in this case to work slightly better, the switch statement should always be faster than the if/elses.

It also would've been interested to see the x86_64 disassembly, but of course then we have the downside of using 64-bit everywhere which leads to larger instruction encodings and the upside of less register spills.

iam··on Better Python Scraping - Installing lxml and Beautiful Soup
XPath/CSS path selectors for scraping are definitely the "now" way to do it. I recommend Nokogiri (http://nokogiri.org/) for the Ruby users, it does pretty much the same thing in a nutshell.

What it really comes down it is 2x-3x smaller code, plus much faster to write it since you can just test your CSS selector in your web browser such as with FireBug before sticking it into your code.

iam··on Team Fortress 2 now free forever
TF2 is not anywhere as competitive as StarCraft 2. There's no ladder, no ranking, no matchmaking..
iam··on Google Chrome Now Blocks Insecure Scripts on HTTPS
I would go one step further and block form input when you are on an HTTP site, to forms that go to HTTPS. This would end the charade of "secure" log-ins on an HTTP page by forcing the login page to be an HTTPS page.
iam··on AMD and ARM's new CPU/GPU virtual ISA
It compromises performance in a similar way to using any byte code vs final machine code. It remains to see how much of a VM support will be required to make this work, as that's typically the large overhead cost of using non-machine code.

If anything the same exact FSAIL will run faster and faster on the same exact hardware as newer JITs come out.

iam··on PopCap Games To Be Acquired For $1 Billion+
Would someone really buy a tablet just to be able to run exclusive games on it? A gaming tablet maybe, but a regular tablet?

Plus, with games like Bejeweled or Plants vs Zombies, it's not exactly hard to duplicate in a matter of weeks and get rid of that exclusive edge.

iam··on Apple’s iCloud Icon Uses The Golden Ratio
HD televisions. They reuse the same LCD panels in monitors and HDTVs.
iam··on Ask HN: Most complete C++0x compiler ?
Judging from this table: GCC 4.x, the later the better. Too bad it'll be a while before we see GCC 4.6!
iam··on Objective-C Blocks vs. C++0x Lambdas: Fight
There's hardly extra complexity in C++0x lambdas, you just need the & or = character to specify if variables are captured by value or by reference and off you go. You can even save the closure as an auto variable instead of needing to spell out the type! Seems easier to me.

Personally I prefer the C++0x closures precisely because of the reference/value capturing distinction.

iam··on Show HN: Interviewing devs made easy
Wow you can create your own challenges? That's awesome. I've seen some sites like this before, but they usually have a predetermined amount of algorithms.

I always wanted to make my own challenges that would have to be automatically solved by potential candidates, and here it is! Glad someone else did this already.

Edit: I see codio.com does this as well

iam··on Show HN: Interviewing devs made easy
How does this work exactly? I'm on Firefox 3.6 and I can't type anything into the box. Same goes for IE8.

I don't know who you're targeting, but I certainly don't expect interview candidates to be running the latest and greatest.

Finally, the URL is way too complicated to give out over the phone... oops?

← PreviousPage 4 of 5Next →