[split] ForkJoinScheduler: group tasks in local scheduler; split when blocking

Problem

The current ForkJoin scheduler forks all tasks locally. This typically
leads to very fine-grained work being scheduled directly by the FJ
pool.

Solution

We introduce a form of coarsening by using a
com.twitter.concurrent.LocalScheduler to schedule thread-local tasks.
During managed blocking, we flush the local schedule by forking their
tasks individually. This allows us to coarsen the work and prevent
over-stealing.

Results

Hopefully better performance on a typical Finagle service.

RB_ID=330121
[split] util-core: Fixes detachable semantics with ConstFuture Problem Promise.attached on ConstFutures didn't work as you'd expect, which would be that it would fulfil the Promise and then detach it.

Solution
Changes the parent.respond to execute outside of the class initialization.

Result
Promise.attached is significantly easier to reason about with ConstFutures.

RB_ID=331505
[split] Spool: Make lazier

Problem

The map/flatMap/++ combinators for Spool were not acting lazily, although that would be the expectation when a Spool is constructed using the lazy constructor. Consumers have built their own workarounds in a few places to deal with this behavior.

Solution

For implementation simplicity, all internal construction of Spools is now lazy via explicit calls to LazyCons. This is validated by tests with a poisoned tail. Additionally, new methods were added to take advantage of the laziness: takeWhile and force.

Result

map/flatMap/collect/++/etc act lazily, and consumer code has been simplified.

RB_ID=331015
[split] com.twitter.app.App: enforce close grace period

Problem

Apps will hang if their constituent parts do not succesfully close
within the deadline. This stems from the fact that Closable deadlines
are advisory.

Solution

Enforce the timeout.

RB_ID=332601
[split] Make com.twitter.finagle.Name an ADT

Problem

There is currently a proliferation of Name implementations which are
related in all sorts of convoluted ways. This is accidental complexity
due to the fact that the Name interface, being part of Finagle's
public API, remains sacrosanct -- at least for the moment.

Solution

This change tries to simplify things a little by making Name a proper
ADT with two variants: Name.Bound describes a bound address; Name.Free
is an unbound Name whose resolution is determined by a Namer. This
makes the relationships clear, and requires only a small API change.

It also makes clear that, in intermediate computation, there are two
levels of dynamism: the tree itself is dynamic; its nodes are
independently dynamic. There is still confusion between the
relationship of Var.{Neg, Pending, etc..} with that of
Activity.Ok(NameTree.{Neg, Empty}) | Activity.Pending, etc. This is
unfortunate -- ideally, we'd be able to pull all of that out of Addr,
and model it entirely as NameTrees. But this is about as far we can go
without making major API changes.

It also has a simplifying effect on Namer signatures. Namely, binding
is now more explicit:

	def lookup(path: Path): Activity[NameTree[Name]]
	def bind(tree: NameTree[Path]): Activity[NameTree[Name.Bound]]

and it is clear whence dynamism is derived.

I also took the opportunity to unify some of the naming (heh.) around this.
In particular, InterpretingFactory is now BindingFactory.

Result

Nicer API; no functionality changes.

RB_ID=330105
TBR=true
[split] util-core: improves usability of Var and VarSource from java Motivation: Prior to this change, using Var.collect required conversion to a scala collection from java, and matching VarSource.Result's was ugly.

Modifications:
Adds Var.collect[A](vars: java.util.List[A]), and VarSource.Result helper methods isOk, isEmpty, isPending, isFailed, and get.

Result:
Tests are passing

RB_ID=327703
[split] LocalScheduler: add LIFO option

Problem

(This problem was described to me by Rohith, as observed in the
adserver.) With current FIFO scheduler, queued work takes presedence,
which can have a destructive effect on network roundtrip times.
Imagine the following scenario:

	def handle(req: Req) = {
	  cache.lookup(key) flatMap { _ => longRunningComputation() }
	  service(req) flatMap { _ => ... }
	}

here, we eagerly call into each service. In reality, due to
pool-checkouts, etc.; actually writing the request to the network will
be queued up in the scheduler. However, the timeout filter will have
scheduled its timeout eagerly (it is further up the stack).

Thus, the longRunningComputation() can prevent the network call from
making it out quickly, and this is exacerbated by the fact that the
timeout has already been scheduled.

Solution

This is an experiment to try out LIFO scheduling. It prevents the
above-described scenario since the future work will get ahead of the
the previously scheduled work. It arguably also makes more intuitive
sense since scheduling bears closer resemblance to the lexical
arrangement of work.

Result

Faster RPC roundtrips for the adserver (and possibly similar
services); fewer timeouts.

RB_ID=332481
[split] util: Add a new sbt target to publish locally to m2

Problem

Publishing the maven-scrooge-plugin requires having access to the latest util.
Every time we publish, we need to wait for the util release to be available on Sonatype.

Solution

Rather than waiting for the release to be available on Sonatype, this new sbt target
installs it locally.

Result

./sbt +publish-m2 publish the jars in the local maven repository

RB_ID=337145
[split] util-core: Fix misspelled word in Promise Scaladoc

RB_ID=338371
NO-QUEUE=true
[split] finagle: Fixes the sbt build Problem http://bigbird.sf.office.twttr.net/job/sbt-continuous-testing/60/console

Solution
Updated util, finagle Build.scalas

Result
sbt-continuous-test no longer fails

RB_ID=339213
[split] [util-core] special case buf.slice(0, buf.length)

Problem

buf.slice can be called with i = 0 and j >= length. This causes an
unnecessary copy to be made.

Solution

Special cases this to return the same buf.

Result

slice() can be called without having to check for this case or worry
about unnecessary allocations.

RB_ID=336549
[split] ChannelTransport: don't discard outstanding readq elements

Problem

There exists a race between fully reading a queue and failing it due
to some exception (e.g. channel closed). This was observed in
streaming HTTP with Connection: close, where a server will send data
and then immediately close the connection. Thus a race between fully
reading the stream and the server closing the connection.

Solution

Add an option to AsyncQueue.fail to not discard the queue, but instead
wait to fail pollers until any pending elements have been read.

Result

No more races.

RB_ID=342467
[split] SS2: memoize path parses

This should quiesce allocation on changes.

RB_ID=341779
[split] util-core: Clarify how Locals get passed Problem I realized today that I didn't understand how Locals worked.  I asked Marius and he explained.

Solution
Updated the docs with what Marius explained.

Result
There's a little more documentation for understanding Locals.

RB_ID=337755
[split] bump util to 6.15.1-SNAPSHOT

RB_ID=345571
TBR=true
NO-QUEUE=true