5 ms·
How Hacker News ranking algorithm works
- bergie 16y agoI built a reasonably similar ranking system a few years ago, but also taking social media interaction (blog links, delicious bookmarks, etc) with the content items being ranked into account: http://bergie.iki.fi/blog/calculating_news_item_relevance/ http://bergie.iki.fi/blog/calculating_news_item_relevance/ You can see it in action on maemo.org: http://maemo.org/news/ http://maemo.org/news/ PHP sources: http://trac.midgard-project.org/browser/branches/ragnaroek/midcom/org.maemo.socialnews http://trac.midgard-project.org/browser/branches/ragnaroek/m...
- b_emery 16y agoLooks like there is a built in max lifetime of about 5-10 hrs.
- brianbreslin 16y agoso this means you'd be best served to submit something at or nearest peak hours? what are the peak use hours on HN? since everyone is a hacker, i'd assume it was evening hours on east and west coast US as heaviest load? not 9-5 ET?
- pavel_lishin 16y agoDon't forget employed people with ADD, or people who are bored at work, who stroll over here when they need a break from their job.
- kens 16y agoFor more details on the algorithm, see my article "Inside the news.yc ranking formula" from last year: http://www.arcfn.com/2009/06/how-does-newsyc-ranking-work.html http://www.arcfn.com/2009/06/how-does-newsyc-ranking-work.ht...
- d0m 16y agoI thought the "secret sauce" was hidden from Arc sources..?
- tptacek 16y agoMy understanding is that the actual HN implementation is heavily customized and not public.
- grourk 16y agoMaybe what's hidden is the code for determining what counts as a vote. e.g., multiple votes from the same IP may be discounted or simply counted as a single vote. Or a bunch of votes coming from fresh accounts created at or after submission time.
- weaksauce 16y agoThat algorithm has been in the source for a while. What is unknown is the current constants and if he changed it at all since first publishing it.
- deleted 16y ago[deleted]
- 10smom 16y agoThanks for the info! now I need to get my son to explain to me. :)
- 10smom 16y agoThanks for the info! now I need to get my son to explain to me. :)
- callmeed 16y agoSo, if you're implementing this in a framework like Django or Rails, can you get a result set in this order directly from a query? Or do you have to query then sort?
- endtime 16y agoIn Django, you could make the ranking score a property of the model and then do query.order_by('-score').
- jacquesm 16y agoThis is not the 'hacker news' ranking algorithm, this is the ranking algorithm distributed with 'ARC', which is the basis for the HN algorithm, but definitely not equal to it. The biggest missing ingredients are flagged posts dropping off quicker and posts that contain no URL dropping off quicker but there are quite a few other subtle tweaks. The (very good) reason why the ARC sources do not give out the real ranking algorithm is to make it a bit harder to game the system.
- jackowayed 16y agoHe glossed over it, but this code does include URL-free posts dropping off faster. See the stuff dealing with "nourl-factor*". I don't know arc at all, but it appears that having no URL multiplies your final score by a factor of .4, meaning that it's ranked almost 3x lower than it otherwise would be. That surprises me; I've noticed that Ask HN get rated lower, but it doesn't seem that extreme. So is Hacker News is a fork of news.arc, rather than straight news.arc? I figured it was, but never heard that officially (since people refer to news.arc as the HN "source code"). Edit: Also, the "lightweight" thing is interesting. There's something in place that sees if the post is a "rallying cry" or is mostly made of images. Additionally, if you link directly to an image file, or to some list of domains that have been deemed lightweight, that'll get marked as lightweight as well. Lightweight posts have a .3 factor, meaning that they're even more deflated than URL-free posts.
- jacquesm 16y agoAh yes, you're right, the 'nourl' is there, it's in the arc bit, but I couldn't find that in the graphs or in the python code.
- amix 16y agoThe current HN algorithm probably follows the same basic idea, but the implementation is more complex because of spammers. I did a fast test of how placements would look like with the vanilla HN algorithm using the current frontpage: http://paste.plurk.com/show/316811/ http://paste.plurk.com/show/316811/ The code to generate the new sorting: http://paste.plurk.com/show/316812/ http://paste.plurk.com/show/316812/ As you can see the rankings are not the same, but very similar...
- DeusExMachina 16y agoDoes anybody care to explain the strange indentation I see in the Arc code? I know Lisp a little (mostly Clojure), but I don't get the indentation of the code at the bottom of the algorithm where it looks like it's branching in two parts. Is this peculiar to Arc? Or to other Lisps as well?
- pmjordan 16y agoI've barely looked at Arc[1] but as far as I remember, the if macro/special form allows an arbitrary number of argument forms, a bit like a combination of Clojure/CL's if and cond: (if cond1 expr1 cond2 expr2 .. .. condN exprN else-expr) With an even number of arguments, there is no else-expr (the same as CL/Clojure cond). The indentation is probably to distinguish between condition and conditional expression - the second column is what could be evaluated and returned from the whole expression. [1] I too use Clojure
- twism 16y agoDoesn't stray that much from clojure, so I think it's a lisp thing. To keep bindings in clojure with different length names more readable, people tend to indent like this: (let [really-long-name l score (get-score x) position (get-pos) x) test test] (... ....))))) Sort of the same effect in the arc snippet in OP.
- rntz 16y agoThat's because of the way Arc does if-expressions. In Scheme and Common Lisp, you have two conditional forms: 'if and 'cond. 'if takes three arguments (or two, with an implied nil, in CL), and is analogous to an if-then-else in other languages: > (if #t 'then 'else) then > (if #f 'then 'else) else 'cond, in contrast, takes as many branches as you like, but they're parenthesized like so: > (cond (#f 'a) (#t (display "I can have a body here!\n") 'b) (#t 'c)) I can have a body here! b In arc, there's just 'if, which is like 'cond with a lot of implicit parenthesization and else-branches: arc> (if t 'then 'else) then arc> (if nil 'then) ; if no else-branch is given, nil is implied nil arc> (if nil 'a t (do (prn "'do is like Scheme's 'begin or CL's 'progn.") 'b) 'else) 'do is like Scheme's 'begin or CL's 'progn. b
- yesbabyyes 16y agoHere's an explanation of other ranking algorithms, including Bayesian average, Wilson score and the ones used on HN, Reddit, StumbleUpon and Del.icio.us: http://blog.linkibol.com/2010/05/07/how-to-build-a-popularity-algorithm-you-can-be-proud-of/ http://blog.linkibol.com/2010/05/07/how-to-build-a-popularit...
- barrkel 16y agoA problem (IMHO) with the HN ranking algorithm is that once a post fails to get traction (perhaps because things were busy at the time it was submitted), it won't really be able to get traction later, even if it's re-discovered 6 hours or 2 days later. Seems to me like velocity ought to be taken into account a little more for items that have otherwise languished.
- wensing 16y agoThis has been the case with my bootstrapping post. It has been revived a few times thanks to tweets and other references since its initial publication to HN, but it has never risen back to where it was, even though it has twice as many points as it did 11 days ago.
- gojomo 16y agoSome weaknesses of this algorithm are: (1) Wall-clock hours penalize an article even if no one is reading (overnight, for example). A time denominated in ticks of actual activity (such as views of the 'new' page, or even upvotes-to-all-submissions) might address this. (2) An article that misses its audience first time through -- perhaps due to (1) or a bad headline -- may never recover, even with a later flurry of votes far beyond what new submissions are getting. Without checking the exact numbers, consider a contrived example: Article A is submitted at midnight and 3 votes trickle in until 8am. Then at 8am article B is submitted. Over the next hour, B gets 6 votes and A gets 9 votes. (Perhaps many of those are duplicate-submissions that get turned into upvotes.) A has double the total votes, and 50% more votes even in the shared hour, but still may never rank above B, because of the drag of its first 8 hours. (I think you'd need to timestamp each vote for an improved decay function.)
- amix 16y agoThe thing I like about HN's ranking algorithm is how simple it is. Implementing something more sophisticated would require more work and probably much better servers. Recently, I have been implementing a ranking algorithm and I started in the wrong direction by taking all kinds of things into consideration. This is dangerous because you spend a lot of time on something that is mostly irrelevant. The bottom line is that HN's algorithm works pretty well for the majority of cases. There are some edges, but solving them would not be trivial and would require a lot more work.
- gojomo 16y agoI'd agree simple is better. Of the two suggestions, replacing hours with artificial ticks adds very little complexity: it's the same formula, with one value replaced, and the accompanying factor adjusted. (The ticks might be submission-count, upvote-count, visit-count, or anything else trivially tallied -- it may not make much difference, except that over time greater activity could require adjusting the tick-deflator-factor.)
- jshen 16y ago
- gsivil 16y agoNice post. Do you know what is the algorithm for the ranking of comments? I think this would be interesting to write about that too.
- pg 16y agoThat's close to the current version, but a little out of date. Here's the code running now: (= gravity* 1.8 timebase* 120 front-threshold* 1 nourl-factor* .4 lightweight-factor* .17 gag-factor* .1) (def frontpage-rank (s (o scorefn realscore) (o gravity gravity*)) (* (/ (let base (- (scorefn s) 1) (if (> base 0) (expt base .8) base)) (expt (/ (+ (item-age s) timebase*) 60) gravity)) (if (no (in s!type 'story 'poll)) .8 (blank s!url) nourl-factor* (mem 'bury s!keys) .001 (* (contro-factor s) (if (mem 'gag s!keys) gag-factor* (lightweight s) lightweight-factor* 1)))))
- sahillavingia 16y agoFor those who aren't well versed in Arc or Lisp, could someone go through the differences?
- tel 16y agoAppears to be substantially identical to what's outlined in the post. The only changes are in the penalties dealt out by the type of story, inclusion of a url, buried status, gagged status, and the operation of penalties due to the contro(versial?)-factor function. If you're just submitting interesting URLs and worry about them being shunted off the main page by gravity then there are no practical differences.
- deleted 16y ago[deleted]
- deleted 16y ago[deleted]
- qeorge 16y agoI made an HN filter for myself, that's basically: points / comments It works shockingly well. Its here if anyone would like to check it out: http://www.upthread.com/ http://www.upthread.com/
- fizx 16y agoYep, you basically have a controversy filter.
- antirez 16y agoWhen I built oknotizie.virgilio.it many years ago, more or less at the same time reddit was created, I used the same base algorithm, that is: RANK = SCORE / AGE^ALPHA, where ALPHA is the obsolescence factor. This is a pretty obvious algorithm, but the evil is in the details. First, since oknotizie is based in italy AGE is calculated in a special way so that nightly hours are calculated in a different way (every hour should be take into account proportionally to the traffic that there is in this hour). Second, there is to do a lot of filtering. Oknotizie is completely built out of anti-spamming: statistical analysis on users voting patterns, cycles detection, an algorithm penalizing similarities in general in the home page, and so forth. To run a simple HN style site is simple as long as the community is not trying hard to game it. Otherwise it starts to get a much more complex (and sad) affair.
- johns 16y agoThe home page algorithm seems to have changed recently, but the RSS feed hasn't and is much noisier. It would be nice to see the RSS feed updated to reflect the home page changes (or confirmation that I'm just perceiving a difference that doesn't actually exist).
- tamersalama 16y agoA basic question: If this was performed on page load, and in-memory, how would the first db fetch occur? Unless this is pushed 'somehow' to the database.