optymizer1's comments

optymizer1 | 12 years ago | on: A RESTful Micro-Framework in Go

You could even go further and assume all user resources are logical extensions of sleepy.Resource:

  type HelloResource struct {
    sleepy.Resource
  }
This makes it clear that you're inheriting everything from sleepy.Resource, so you can provide reasonable implementations for all methods of resources, not just HTTP methods handlers, e.g. getBodyAsJSON(), redirect(resource), etc.

Also, depending on how your mux works, you could store app-level data in sleepy.Resource, to be accessed by all resources:

  sleepy.Resource.DB
  sleepy.Resource.Session
  sleepy.Resource.Root
and other things I can't think of right now.

optymizer1 | 12 years ago | on: Fake Name Generator

Russian first names (not Cyrillic) are very strange: "Innocent Korovin" - really? Russian (cyrillic) seem more realistic though.

optymizer1 | 12 years ago | on: Ask HN: Which language/web framework to learn for employability?

Here's an advice: browse for job posts you'd be interested in. Look at required/preferred qualifications. Start learning those. When ready, apply for those kinds of jobs.

Also, find out what other libraries/API they might use. For example, the company could be using some niche software that's nice to know, but it wasn't important enough to list in the job description. The HR people won't care if you say that you know X, but you might impress a fellow developer during the interview, and that's a plus.

optymizer1 | 12 years ago | on: Dangerous Embedded C Coding Standard Rules (2011)

In C, variables have function-level storage. I don't recall the actual term from the C standard, but the storage for _all_ variables declared in any blocks inside a function is allocated at the beginning of the function, when the stack frame is set up. So there is 'no way' to create 'temp' only inside the if block.

optymizer1 | 12 years ago | on: Dangerous Embedded C Coding Standard Rules (2011)

That's the obvious next step, but it's not valid C89 and that may or may not be relevant for people doing embedded programming. Personally, I'm all for using newer standards and declaring variables locally when it makes sense. Sometimes I like to see all variables at the top of the function though.

optymizer1 | 12 years ago | on: Dangerous Embedded C Coding Standard Rules (2011)

I'm not completely on board with #4 (initialization of variables). I agree that 'declaring and then assigning a value' _within the same block_ vs 'initialized declaration' has no speed gains, only downsides.

However, if the assignment can happen in a _different block_ (maybe inside an 'if' block) you could save 1 memory write, depending on how many times the if condition is satisfied.

This obviously optimizes for speed at the expense of maintainability, and it's for the programmer to make intelligent trade offs, but the fact is that one method is faster than the other.

Silly example that decrements 'a' repeatedly if condition is non-zero:

   //temp = 0 inside if block
   int dec(int a, int condition) {
       int temp;

       if (condition) {
           temp = 0;  //<-- memory write depends on condition

           //compute something here in a loop
           while (temp < a) {
               a -= (temp++);
           }
       }

       return a;
   }

   //temp = 0 at declaration
   int dec2(int a, int condition) {
       int temp = 0; // <-- memory write always executed

       if (condition) {
           //compute something here in a loop
           while (temp < a) {
               a -= (temp++);
           }
       }

       return a;
   }

We can disassemble the output to verify that dec() will only write to memory if the condition was satisfied (see 400458), while dec2() will always write into temp (see 400482):

    # <dec>
    400448:  push   %rbp
    400449:  mov    %rsp,%rbp
    40044c:  mov    %edi,0xffec(%rbp)
    40044f:  mov    %esi,0xffe8(%rbp)
    400452:  cmpl   $0x0,0xffe8(%rbp)  # if (condition)
    400456:  je     400473 <dec+0x2b>
    400458:  movl   $0x0,0xfffc(%rbp)  # temp = 0 <-- depends on condition
    40045f:  jmp    40046b <dec+0x23>  # while
    400461:  mov    0xfffc(%rbp),%eax
    400464:  sub    %eax,0xffec(%rbp)
    400467:  addl   $0x1,0xfffc(%rbp)
    40046b:  mov    0xfffc(%rbp),%eax
    40046e:  cmp    0xffec(%rbp),%eax
    400471:  jl     400461 <dec+0x19>  # loop
    400473:  mov    0xffec(%rbp),%eax  # return a
    400476:  leaveq
    400477:  retq

    # <dec2>
    400478:  push   %rbp
    400479:  mov    %rsp,%rbp
    40047c:  mov    %edi,0xffec(%rbp)   
    40047f:  mov    %esi,0xffe8(%rbp)
    400482:  movl   $0x0,0xfffc(%rbp)   # temp = 0 <-- always executed
    400489:  cmpl   $0x0,0xffe8(%rbp)   # if (condition)
    40048d:  je     4004a3 <dec2+0x2b>
    40048f:  jmp    40049b <dec2+0x23>  # while
    400491:  mov    0xfffc(%rbp),%eax
    400494:  sub    %eax,0xffec(%rbp)
    400497:  addl   $0x1,0xfffc(%rbp)
    40049b:  mov    0xfffc(%rbp),%eax
    40049e:  cmp    0xffec(%rbp),%eax
    4004a1:  jl     400491 <dec2+0x19>  # loop
    4004a3:  mov    0xffec(%rbp),%eax   # return a
    4004a6:  leaveq 
    4004a7:  retq
The above code was compiled with gcc 4.1.2 on amd64/linux. gcc -O2 and gcc -O3 completely do away with the 'temp' variable and generate fewer instructions.

optymizer1 | 12 years ago | on: Snapchat - GibSec Full Disclosure

I hate to be that guy, but what's the big deal? Where's the full disclosure? It looks like they're just documenting the API, which is not really disclosing much. Anyone can fire up burpsuite proxy and inspect HTTP requests and responses from their phone.

Now onto their PoC. So they don't have rate limiting on some API requests. That's pretty dumb for a service with a public API, but in my experience, most websites don't limit requests rate, because it's always a "let's toughen up security" after-thought. I remember GAE having some anti-DDoS measures, so they may be relying on that while growing the business.

The bulk registering of user accounts is more serious though and could be easily fixed (to some extent) with a captcha. This may be worthy of a tweet, maybe. Instead, Gibson listed all of SnapChat's APIs, even though most of them were irrelevant to the PoC, and slapped 'Full Disclosure' on it.

This is high-school level security researching. We were finding the same 'exploits' in high school. You could probably find these with any service that's only starting out. Glad to see that's the best Gibson could do. If I were Snapchat, I'd fix the two issues and then thank Gibson for spending the time to create an API page for SnapChat.

optymizer1 | 12 years ago | on: Web Framework Benchmarks - Round 8

I find the JSON benchmark misleading a bit. I posted this before, but I'll say it again: JSON serialization in Go is slow (2.5x slower than Node.js for example [1]). The web server, however, is very fast. When they measure webserver+json, Go wins because of its webserver, not because it serializes JSON faster. If you want to parse a lot of JSON objects with 1 request (or 1 script), or if you have a large JSON object to parse, Node.js will outperform Go.

That said, I rewrote my app in Go and I'm very happy with the performance, stability and testability. The recently announced go 'cover' tool is very useful and a breeze to use.

[1] Here are my benchmarks: https://docs.google.com/spreadsheet/ccc?key=0AhlslT1P32MzdGR... (includes codepad.org links to the source for each benchmark)

optymizer1 | 12 years ago | on: Writing HTTP Middleware in Go

This is pretty neat. Functions that read from or write to http.Request.Body should be able to accept a Context object, assuming they take a Reader/Writer. If they take an http.Request, you're going to pass in Context.req, similar to how custom.Request would contain a custom.req field.

optymizer1 | 12 years ago | on: Writing HTTP Middleware in Go

Interesting. Now, what does SetUser(r, "dave") do?

Since you're passing in 'r', it must keep a map of all requests and their data, i.e. map[*http.Request]string ("dave" being the string in this case).

This map should be protected by a mutex because it could be written from multiple go-routines.

Is this the case? If so, how do we avoid contention on this mutex?

optymizer1 | 12 years ago | on: After 5 days, my OS doesn't crash when I press a key

I'm not saying that having a bug is something to be ashamed of. I am pointing out that the page is making a big deal out of a small issue, in order to argue a bigger point: operating system development is hard. The whole page screams with: "look how hard this is!".

The lesson conveyed in my post should be that this author is making it look harder than it actually is, and if you want to write an OS, you shouldn't feel like it's an unsurmountable task. But by all means, stamp and destroy it.

page 1