Hacker Newsnew | past | comments | ask | show | jobs | submit | dzderic's commentslogin

A large young gen makes sense since it reduces the frequency of minor GCs but doesn't affect the duration of them, since the running time of a young gen GC is only proportional to the amount of live objects.


Yes it does affect the duration of them. The larger nursery you have, the more gc roots you will need to trace due to write barriers from older generations. So yes you are right that the duration is dependent on the number of live objects at gc time, but the number of live objects is also dependent on the size of the nursery.

(and whoever is down-voting me, maybe you can explain why I'm wrong?)


My understanding is that an entry in the card table is set when an object in young generation is allocated that is referenced by something in the old generation. An entry in the card table corresponds to a 512 byte segment of memory in the old generation. Thus, the cost imposed by this would be based on how many distinct 512 byte segments of the old generation reference any objects in the young generation.

If you have a web service that mostly consists of some baseline of long-lived objects and many short-lived objects used for fulfilling requests, I would expect to have relatively few GC roots. At that point, if you assume that you have a consistent request rate, I would expect the number of reachable objects in the young generation to remain constant regardless of the size of the young generation, and the number of GC roots should also remain constant. Based on that, increasing the young generation size would then decrease the frequency of young generation garbage collection, reduce the probability of survivors getting promoted to old generation, and have no effect on the time it takes to do young generation garbage collection. There certainly applications that have different behavior when the old generation is less static, but I would think for this use case the new generation size should be as big as it can be.

If something I've said is incorrect or incomplete, I'm anxious to know. There are relatively few well-written explanations of how Java garbage collection works, so it is difficult to have confidence regarding it without a lot of practical experience as you have said.


That's a good explanation of why I'm wrong. Basically you are hoping to reach an equilibrium situation in which 0% of the allocated memory in nursery are true survivors. Because if the true survival rate was higher than 0%, then the larger the nursery size the longer the duration between collections and the higher the number of objects that are true survivors.

If you had a perfect situation like that, with a giant nursery, you wouldn't even need to gc anything. When the nursery is full, just start over from address 0 and you can be confident that when the new objects starts overwriting the old that the old will already be unreachable from the object graph.

You never reach that situation in reality. Even in a simple web server some request handling thread might do something innocuous like setting a key in a cache hash somewhere leading to the hash being full and needing to be reallocated. That would dirty mark one card. And again, the longer the duration, the more of these "freak" events you get. Or there may be a string somewhere that keeps track of the current date and when it ticks over from "July 31st, 2015" to "August 1st, 2015" it triggers a reallocation because the last string is one character longer.

It may be that having a large nursery is a good trade-off because for many loads it's the same cards being marked over and over again. That may outweigh the increased frequency of tenured generation collections (memory isn't free so you must take the space from somewhere).


Not an expert but my experience/basic understanding

The old generation gets at lot more expensive as it gets bigger, and I think requires at least some stop the world with all the collectors in hotspot.

New generation collections often remain quick as the size grows as long as most objects are dying young. Increasing the size of new also gives more opportunity for objects to die before being promoted (if you have lots of objects that live just long enough to be promoted it can be a good strategy to increase size of new). New can be collected concurrently.


For anyone who has ever battled with maintaining their own apt/yum repos, this seems like a godsend.

The most-used tools for getting a package into your repo involve scp'ing the file to the repository server and running a command to update its index. It's nice to have a proper toolset to do this, but it's too bad I spend most of my time with YUM nowadays.


man dput


This "solution" will only make it harder for regular folks to execute orders, since HFTs will beat the randomness by shooting multiple orders through multiple order gateways.


Guess we'll need a hierarchical token bucket with stochastic fairness queueing as well.

We don't just need it to be random. We need there to be no way of ever quite knowing if any given order will beat another order to the exchange (within a given time period, of course). They won't know if they can beat joe ordinary, and they definitely won't know if they can beat the other HFT's. That might be enough to put a lid on it.

Edit: For those playing along, here's the metaphor. Joe goes to market to buy sheep. Bill knows Joe is going so he sends a fast runner ahead of him to buy the cheapest sheep in town first so he can mark them up and sell them to Joe when he arrives. We try making everyone wait at the town gate for a random amount of time to give Joe a chance to arrive and get through. So Bill (being very rich) just sends 10 guys so one is very likely to be let in before Joe anyway. Next we introduce the stochastic filter. We make everyone line up and then shuffle the order every once in a while, but Bill still has more guys so he might still get one in first more often than not. Finally, we add the token bucket. For every one guy that we know employed by Bill admitted, we make the next one wait twice as long to get in, so if Joe and 10 Bills show up, Joe and the first Bill are essentially on even footing again because the 2nd through 10th Bill would have to wait too long to matter.


"For those playing along, here's the metaphor. Joe goes to market to buy sheep. Bill knows Joe is going so he sends a fast runner ahead of him to buy the... "

Seriously, how many times have we discussed this issue on this site and we still get this bullshit. Bill doesn't know Joe is going. He doesn't. Get it through your thick heads.


Somewhat farcically perpetuating the metaphor, is it not the case that Bill gets to know that Joe is interested in buying sheep once Joe has bought a few of them? And at that point Bill can outrun Joe and make money from his (very near) future purchases?

That was my reading of the article - it seems that either there is a flow of information from the trading events to the fast traders, or the scenario portrayed in the article was very unlikely (though I guess that couldn't be ruled out given how much trading there is). noonespecial's metaphor seems to apply, what have I misunderstood?


Somewhat farcically perpetuating the metaphor, is it not the case that Bill gets to know that Joe is interested in buying sheep once Joe has bought a few of them?

He doesn't know with certainty. He can guess that's what Joe is doing, but he could be wrong and be stuck with sheep that he can't sell for the price he intends to ask. Every second he owns sheep is a second he's taking a risk that they'll go down in price, not up.


Yes, that makes sense. From what I understood of the article, and it really isn't my area so maybe I got something wrong, a buy order was not filled completely even though there were sell orders available to fill it. Doesn't that mean that people cancelled their orders whilst the buy was being filled, meaning that they must have been able to execute market actions out of order? That would put people who can act quickly at a big advantage on getting the price they wanted, because they can cancel and re-bid at a higher price. Sure it's a gamble, but it seems like one with little to lose.

I've probably misunderstood something, but it certainly seems to be an issue that gets people very exercised. I presume there must be some competitive advantage in being fast, otherwise people wouldn't do it, so surely the only real issue is whether or not the consequence of exercising that advantage is socially advantageous?


Its a somewhat leaky metaphor I grant you. So how does Bill have information about what Joe is doing? Joe certainly tries not to telegraph such things for obvious reasons.

From what I've gathered, through methods like "pinging" the market with many tiny transactions in likely spots, Bill can sound out what Joe is doing in the sheep market. Supposedly the market exchange will also "flash" the information about buy and sell orders to the HFT's in favorable network locations a few ms faster than the general public as well. Figuring out that Joe is buying sheep are what all of the "brilliant minds" that are heading into HFT everyone is talking about are doing. They're watching the road for Joe. Also Joe is not a small investor, he's a rancher that buys lots of sheep. Small investors don't place the kind of orders that HFT can attack.

Do note that this metaphor really only applies to the Front Running section of HFT, and really evolved from a fanciful attempt to coagulate network layer and application layer solutions into one magical unicorn fix. (Its kind of more about how tc works in linux than how markets work. :) )


You should be able to recreate that 1D scatter plot using a regular scatter plot and setting all of the y values to 0 (unless I'm missing something).


Even better, [1] == 1 but [1] != [1]


When you're talking about an average latency of single digit us for a regular switch and < 500ns for a low-end performance switch, the difference between 10 and 20 microseconds is massive.


Packets between internet hosts spend about 10,000,000ns in transit and they traverse around $10,000,000 worth of network elements on the path. These numbers are both worth optimizing. I'd say that the lowest hanging fruit for operating system hackers like myself is the cost i.e. serving more customers with fewer boxes. That latency figure is tougher because it's mostly due to the speed of light rather than processing time.


Accidentally clicked on the wrong icon and downvoted you, sorry, my bad.


I gave a corrective upvote :)


The example cited here is insulting to everyone's intelligence:

  The possibility of representing face cards with a name would likely never occur to you, because it would be too complicated to go through the effort of defining the type of a rank to be a "integer or a class comprised of four case classes -- jack,queen,king,ace".
I'm sure every competent Scala developer will see that the equivalent in Clojure can be done with val King = 13; val Queen = 12; ..., which also means you get ordering for free as you're not mixing ints and keywords.

I do agree with the author's point that Clojure almost forces you to adopt a simpler design, but I feel that long-term maintainability requires a delicate balance of simplicity and structure that can be achieved with Scala, but takes more self-control with Clojure.


Using val King = 13; val Queen = 12; in Scala is not equivalent with using Clojure keywords, as their printed variant will be 13 and 12, not :king and :queen. Reading debugging output or logs would force you to manually convert those values.

Ordering for free is valuable, I guess, but it sort of depends on the situation. Sometimes face cards are worth 10, other times they are worth 11, 12, 13. If you use val King = 10;, then it suddenly is impossible to distinguish between face cards and tens.


Right, if you wanted to have an ordering around, you would use an enum. The enum's values would print as Ace, 2, 3, 4, ..., Jack, Queen, King, and then when you wanted to implement a particular game the game could define the mapping from rank -> set of possible values. You wouldn't want to map each rank to a single value, since in commonly played games aces are worth both 1 and 11 or both 1 and 14.

If you didn't want the ordering (or the compiler warning when your blackjack implementation omits queens), you could use Scala's symbols, which are more or less the same as Clojure's keywords:

  scala> 'king
  res0: Symbol = 'king


Or use value classes and get the best of both worlds.


No, your first sentence is wrong. The following definition stores the ranks as unboxed integers, but prints them differently:

    case class Rank private (val rank : Int) extends AnyVal {
      override def toString() = {
        rank match {
          case 1 => "A" 
          case 11 => "J"
          case 12 => "Q"
          case 13 => "K"
          case _ => rank.toString()
        }
      }
    }   

    object Rank {
       val Ace = Rank(1)
       val Two = Rank(2)
       // ...
       val King = Rank(13)
    }


And you can create a new string interpolation to make card instances, like:

    card"Heart:Ace"
or

    card"$suite:Ace" if you want to reference a variable.


A while loop and temporary mutable variables are definitely not the Pythonic way of doing this. More idiomatic:

    $ time python -c 'print sum(xrange(100000000 + 1))'
    5000000050000000
    
    real    0m1.398s
    user    0m1.383s
    sys     0m0.012s
Comparison to baseline:

    $ time (echo -e 'n=0 \ni=0 \nwhile (i <= 100000000): \n  n += i \n  i += 1 \n\nprint(n)\n' | python)
    5000000050000000
    
    real    0m33.140s
    user    0m32.939s
    sys     0m0.023s


I see. That is good to know; I merely chose mutating global variables in a loop because I knew how to do that in both languages. (I am not very familiar with Python.) That is not the idiomatic way to do it in Arc, either. I would normally use a recursive function, like this:

  arc> (time:xloop (i 0 n 0) (if (> i 100000000) n (next (+ i 1) (+ n i))))
  time: 9121 cpu: 9130 gc: 0 mem: 480  ; the times are in msec
  5000000050000000
Or perhaps a "higher-order function":

  arc> (time:sum idfn 1 100000000)
  time: 19889 cpu: 19908 gc: 0 mem: 1224
  5000000050000000
Or use a deforestation macro that I wrote, which is closest to your Python example:

  arc> (time:thunkify:reduce + (range 1 100000000))
  time: 17971 cpu: 17985 gc: 0 mem: 3592
  5000000050000000
Also, here's what you can get by dropping into Racket:

  arc> (time:$:let loop ((i 0) (n 0)) (if (> i 100000000) n (loop (+ i 1) (+ n i))))
  time: 402 cpu: 403 gc: 0 mem: 920
  5000000050000000
I suppose Python has an analogue of that--dropping into C, or at least loading C libraries. Which Racket can do too. Mmm.


After finishing the Cousera crypto course, I did a quick review of their approach and found 2 issues which completely broke their authentication protocol (https://github.com/saltstack/salt/issues/2239 & https://github.com/saltstack/salt/issues/2916).


Which they seemed to fix pretty quickly, mainly by migrating to keyczar.


Which is one of the reasons I like them as much as I do. I can watch the iterations, they work hard on their product are committed to open source, and release regularly and often.

The other big win for me is I can read their code, I understand python & have a number of items I'll be able to contribute to upstream that will help others use the product.


What kind of performance are you getting, and how many nodes do you have?


We have a 14 node cluster, the nodes have anywhere between 4-6 disks. Performance has been pretty amazing, we can do ad-hoc queries on this 4.5B row table. Each node has read throughput at about ~1.3GB/s for full table scans (data is snappy compressed, store as RCFile: columnar).


That sounds pretty fantastic - when you say "ad-hoc" do you mean that it's fast enough to be directly queried from a UI - are we talking seconds or minutes for your queries?

What drawbacks have you found with Impala? I've been keeping an eye on it, and also Shark: http://shark.cs.berkeley.edu/


It depends, if you plan to scan our entire data set it could take 30-40 seconds (roughly ~2.8TB), but we have our data partitioned based on a key that makes sense for the kind of data you'd need to populate a web page and these queries are fast enough (< 2 seconds) for aggregations that come in via AJAX.

We haven't yet had a chance to optimize our environment either. For example, our nodes are still running a pretty old version of CentOS, so we have LLVM disabled (which would help a lot for huge batch computations...see http://blog.cloudera.com/blog/2013/02/inside-cloudera-impala...).

Also, our data is stored in RCFile, which is not exactly the most optimized columnar storage format. We're working on a plan to get everything over the new Parquet (http://parquet.io/) columnar format for another boost in performance.

We haven't come across any real drawbacks using Impala as of yet, it fits our needs pretty well.

Disclaimer: I work for Cloudera in their internal Tools Team, we like to dog food our stuff :).

Edit: One drawback of Impala is the lack of UDF support, but this is something that will be coming in a later release.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: