anchor.diff:  
   send_changes(Args, Acc0, FirstRound) ->
       #changes_args{
  -        dir = Dir,
  -        filter = FilterName,
  -        filter_args = FilterArgs
  +        dir = Dir
       } = Args,
       #changes_acc{
           db = Db,
  -        seq = StartSeq
  +        seq = StartSeq,
  +        filter = Filter
       } = Acc0,
  -    case FirstRound of
  -    true ->
  -        case FilterName of
  -        "_doc_ids" when length(FilterArgs) =< ?MAX_DOC_IDS ->
  -            send_changes_doc_ids(
  -                FilterArgs, Db, StartSeq, Dir, fun changes_enumerator/2, Acc0);
  -        "_design" ->
  -            send_changes_design_docs(
  -                Db, StartSeq, Dir, fun changes_enumerator/2, Acc0);
  +    EnumFun = fun ?MODULE:changes_enumerator/2,
  +    case can_optimize(FirstRound, Filter) of
  +        {true, Fun} ->
  +            Fun(Db, StartSeq, Dir, EnumFun, Acc0, Filter);
           _ ->
  -            couch_db:changes_since(
  -                Db, StartSeq, fun changes_enumerator/2, [{dir, Dir}], Acc0)
  -        end;
  -    false ->
  -        couch_db:changes_since(
  -            Db, StartSeq, fun changes_enumerator/2, [{dir, Dir}], Acc0)
  -    end.
  -
  -
  -send_changes_doc_ids(DocIds, Db, StartSeq, Dir, Fun, Acc0) ->
  +            couch_db:changes_since(Db, StartSeq, EnumFun, [{dir, Dir}], Acc0)
  +    end.
  +
  +
  +can_optimize(true, {doc_ids, _Style, DocIds})
  +        when length(DocIds) =< ?MAX_DOC_IDS ->
  +    {true, fun send_changes_doc_ids/6};
  +can_optimize(true, {design_docs, _Style}) ->
  +    {true, fun send_changes_design_docs/6};
  +can_optimize(_, _) ->
  +    false.
  +
  +
  +send_changes_doc_ids(Db, StartSeq, Dir, Fun, Acc0, {doc_ids, _Style, DocIds}) ->
       Lookups = couch_btree:lookup(Db#db.id_tree, DocIds),
  -    FullDocInfos = lists:foldl(
  -        fun({ok, FDI}, Acc) ->
  -            [FDI | Acc];
  -        (not_found, Acc) ->
  -            Acc
  -        end,
  -        [], Lookups),
  -    send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0).
  -
  -
  -send_changes_design_docs(Db, StartSeq, Dir, Fun, Acc0) ->
  +    FullInfos = lists:foldl(fun
  +        ({ok, FDI}, Acc) -> [FDI | Acc];
  +        (not_found, Acc) -> Acc
  +    end, [], Lookups),
  +    send_lookup_changes(FullInfos, StartSeq, Dir, Db, Fun, Acc0).
  +
  +
  +send_changes_design_docs(Db, StartSeq, Dir, Fun, Acc0, {design_docs, _Style}) ->
       FoldFun = fun(FullDocInfo, _, Acc) ->
           {ok, [FullDocInfo | Acc]}
       end,
       KeyOpts = [{start_key, <<"_design/">>}, {end_key_gt, <<"_design0">>}],
  -    {ok, _, FullDocInfos} = couch_btree:fold(
  -        Db#db.id_tree, FoldFun, [], KeyOpts),
  -    send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0).
  +    {ok, _, FullInfos} = couch_btree:fold(Db#db.id_tree, FoldFun, [], KeyOpts),
  +    send_lookup_changes(FullInfos, StartSeq, Dir, Db, Fun, Acc0).
   
   
   send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0) ->
       FoldFun = case Dir of
  -    fwd ->
  -        fun lists:foldl/3;
  -    rev ->
  -        fun lists:foldr/3
  +        fwd -> fun lists:foldl/3;
  +        rev -> fun lists:foldr/3
       end,
       GreaterFun = case Dir of
  -    fwd ->
  -        fun(A, B) -> A > B end;
  -    rev ->
  -        fun(A, B) -> A =< B end
  -    end,
  -    DocInfos = lists:foldl(
  -        fun(FDI, Acc) ->
  -            DI = couch_doc:to_doc_info(FDI),
  -            case GreaterFun(DI#doc_info.high_seq, StartSeq) of
  -            true ->
  -                [DI | Acc];
  -            false ->
  -                Acc
  -            end
  -        end,
  -        [], FullDocInfos),
  +        fwd -> fun(A, B) -> A > B end;
  +        rev -> fun(A, B) -> A =< B end
  +    end,
  +    DocInfos = lists:foldl(fun(FDI, Acc) ->
  +        DI = couch_doc:to_doc_info(FDI),
  +        case GreaterFun(DI#doc_info.high_seq, StartSeq) of
  +            true -> [DI | Acc];
  +            false -> Acc
  +        end
  +    end, [], FullDocInfos),
       SortedDocInfos = lists:keysort(#doc_info.high_seq, DocInfos),
       FinalAcc = try
  -        FoldFun(
  -            fun(DocInfo, Acc) ->
  -                case Fun(DocInfo, Acc) of
  +        FoldFun(fun(DocInfo, Acc) ->
  +            case Fun(DocInfo, Acc) of
                   {ok, NewAcc} ->
                       NewAcc;
                   {stop, NewAcc} ->
                       throw({stop, NewAcc})
  -                end
  -            end,
  -            Acc0, SortedDocInfos)
  +            end
  +        end, Acc0, SortedDocInfos)
       catch
  -    throw:{stop, Acc} ->
  -        Acc
  +        {stop, Acc} -> Acc
       end,
       case Dir of
  -    fwd ->
  -        {ok, FinalAcc#changes_acc{seq = couch_db:get_update_seq(Db)}};
  -    rev ->
  -        {ok, FinalAcc}
  +        fwd -> {ok, FinalAcc#changes_acc{seq = couch_db:get_update_seq(Db)}};
  +        rev -> {ok, FinalAcc}
       end.
   
   
  
positive.code:         dir = Dir,
          since = Since
      } = Args1,
      {FilterFun, FilterArgs} = make_filter_fun(FilterName, Style, Req, Db0),
      Args = Args1#changes_args{filter_fun = FilterFun, filter_args = FilterArgs},
      Start = fun() ->
          {ok, Db} = couch_db:reopen(Db0),
          StartSeq = case Dir of
  
negative.code:     end;
  changes_enumerator(DocInfo, Acc) ->
      #changes_acc{
          filter = Filter, callback = Callback, prepend = Prepend,
          user_acc = UserAcc, limit = Limit, resp_type = ResponseType, db = Db,
          timeout = Timeout, timeout_fun = TimeoutFun
      } = Acc,
      #doc_info{high_seq = Seq} = DocInfo,
      Results0 = filter(Db, DocInfo, Filter),
      Results = [Result || Result <- Results0, Result /= null],
      Go = if (Limit =< 1) andalso Results =/= [] -> stop; true -> ok end,
      case Results of
  