Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Keep channels pre-sorted after addition. It speedups 60%, because we …

…need less cursor comparisions.
  • Loading branch information...
commit 7b43e89289202503c3827873a62d8259fb968494 1 parent 66b0dc1
@DmitryKoterov authored
View
20 Realplexor/Common.pm
@@ -132,18 +132,21 @@ sub send_pendings {
# Iterate over data items.
ONE_ITEM:
foreach my $item (@$data) {
+ # If we found an element with smaller cursor, abort iteration,
+ # because all elements are sorted by cursor.
+ last if $item->[0] <= $listen_cursor;
# Process a single data item in context of this FH.
my ($cursor, $rdata, $limit_ids) = @$item;
# Filter data invisible to this client.
foreach my $func (@visibility_checkers) {
- next ONE_ITEM if !$func->(
+ next ONE_ITEM if !$func->({
id => $id,
cursor => $cursor,
rdata => $rdata,
limit_ids => $limit_ids,
listen_cursor => $listen_cursor,
listen_pairs => $what_listens_this_fh,
- );
+ });
}
# Hash by dataref to avoid to send the same data
# twice if it is appeared in multiple IDs.
@@ -213,15 +216,12 @@ sub _do_send {
# Called to check visibility of a data block.
sub hook_check_visibility {
- my (%a) = @_;
+ my ($a) = @_;
- # 1. Filter old data.
- return 0 if $a{cursor} <= $a{listen_cursor};
-
- # 2. If this data block has limited visibility, check that
- # current client listens at least one ID in the associated
- # limiter list.
- return 0 if $a{limit_ids} && !grep { $a{limit_ids}{$_->[1]} } @{$a{listen_pairs}};
+ # If this data block has limited visibility, check that
+ # current client listens at least one ID in the associated
+ # limiter list.
+ return 0 if $a->{limit_ids} && !grep { $a->{limit_ids}{$_->[1]} } @{$a->{listen_pairs}};
# OK.
return 1;
View
10 Storage/DataToSend.pm
@@ -17,6 +17,7 @@
package Storage::DataToSend;
use base 'Exporter';
use strict;
+use Tie::Array::Sorted;
our @EXPORT = qw($data_to_send);
our $data_to_send = new Storage::DataToSend();
@@ -32,7 +33,14 @@ sub clear_id {
sub add_dataref_to_id {
my ($this, $id, $cursor, $rdata, $rlimit_ids) = @_;
- push @{$this->{$id}}, [$cursor, $rdata, $rlimit_ids];
+ my $list = $this->{$id};
+ if (!$list) {
+ $list = $this->{$id} = [];
+ tie @$list, "Tie::Array::Sorted", sub { $_[1][0] <=> $_[0][0] };
+ }
+ # TODO: in most cases new cursor is greater than the first array
+ # element, so we may unshif it without re-sorting to speedup.
+ push @$list, [$cursor, $rdata, $rlimit_ids];
}
sub get_data_by_id {
View
130 Tie/Array/Sorted.pm
@@ -0,0 +1,130 @@
+package Tie::Array::Sorted;
+
+use 5.006;
+
+use strict;
+use warnings;
+
+use base 'Tie::Array';
+
+our $VERSION = '1.41';
+
+=head1 NAME
+
+Tie::Array::Sorted - An array which is kept sorted
+
+=head1 SYNOPSIS
+
+ use Tie::Array::Sorted;
+
+ tie @a, "Tie::Array::Sorted", sub { $_[0] <=> $_[1] };
+
+ push @a, 10, 4, 7, 3, 4;
+ print "@a"; # "3 4 4 7 10"
+
+=head1 DESCRIPTION
+
+This presents an ordinary array, but is kept sorted. All pushes and
+unshifts cause the elements in question to be inserted in the
+appropriate location to maintain order.
+
+Direct stores (C<$a[10] = "wibble">) effectively splice out the original
+value and insert the new element. It's not clear why you'd want to use
+direct stores like that, but this module does the right thing if you do.
+
+If you don't like the ordinary lexical comparator, you can provide your
+own; it should compare the two elements it is given. For instance, a
+numeric comparator would look like this:
+
+ tie @a, "Tie::Array::Sorted", sub { $_[0] <=> $_[1] }
+
+Whereas to compare a list of files by their sizes, you'd so something
+like:
+
+ tie @a, "Tie::Array::Sorted", sub { -s $_[0] <=> -s $_[1] }
+
+=head1 LAZY SORTING
+
+If you do more stores than fetches, you may find
+L<Tie::Array::Sorted::Lazy> more efficient.
+
+=cut
+
+sub TIEARRAY {
+ my ($class, $comparator) = @_;
+ bless {
+ array => [],
+ comp => (defined $comparator ? $comparator : sub { $_[0] cmp $_[1] })
+ }, $class;
+}
+
+sub STORE {
+ my ($self, $index, $elem) = @_;
+ splice @{ $self->{array} }, $index, 0;
+ $self->PUSH($elem);
+}
+
+sub PUSH {
+ my ($self, @elems) = @_;
+ ELEM: for my $elem (@elems) {
+ my ($lo, $hi) = (0, $#{ $self->{array} });
+ while ($hi >= $lo) {
+ my $mid = int(($lo + $hi) / 2);
+ my $mid_val = $self->{array}[$mid];
+ my $cmp = $self->{comp}($elem, $mid_val);
+ if ($cmp == 0) {
+ splice(@{ $self->{array} }, $mid, 0, $elem);
+ next ELEM;
+ } elsif ($cmp > 0) {
+ $lo = $mid + 1;
+ } elsif ($cmp < 0) {
+ $hi = $mid - 1;
+ }
+ }
+ splice(@{ $self->{array} }, $lo, 0, $elem);
+ }
+}
+
+sub UNSHIFT { goto &PUSH }
+
+sub FETCHSIZE { scalar @{ $_[0]->{array} } }
+sub STORESIZE { $#{ $_[0]->{array} } = $_[1] - 1 }
+sub FETCH { $_[0]->{array}->[ $_[1] ] }
+sub CLEAR { @{ $_[0]->{array} } = () }
+sub POP { pop(@{ $_[0]->{array} }) }
+sub SHIFT { shift(@{ $_[0]->{array} }) }
+
+sub EXISTS { exists $_[0]->{array}->[ $_[1] ] }
+sub DELETE { delete $_[0]->{array}->[ $_[1] ] }
+
+1;
+
+=head1 AUTHOR
+
+Original author: Simon Cozens
+
+Current maintainer: Tony Bowden
+
+=head1 BUGS and QUERIES
+
+Please direct all correspondence regarding this module to:
+ bug-Tie-Array-Sorted@rt.cpan.org
+
+This module was originall written as part of the L<Plucene> project.
+However, as Plucene no longer uses this, it is effectively unmaintained.
+
+=head1 COPYRIGHT AND LICENSE
+
+ Copyright (C) 2003-2006 Simon Cozens and Tony Bowden.
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License; either version 2 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+
+=cut
+
View
8 t/servertest/320_rotate_queue.phpt
@@ -35,8 +35,8 @@ IN ==> Content-Type: text/plain
IN ==> Content-Length: 259
IN ==>
IN ==> [data_to_send]
-IN ==> abc => [*: 3b], [*: 4b]
-IN ==> def => [*: 3b], [*: 4b]
+IN ==> abc => [*: 4b], [*: 3b]
+IN ==> def => [*: 4b], [*: 3b]
IN ==>
IN ==> [connected_fhs]
IN ==>
@@ -57,8 +57,8 @@ IN ==> Content-Type: text/plain
IN ==> Content-Length: 259
IN ==>
IN ==> [data_to_send]
-IN ==> abc => [*: 4b], [*: 5b]
-IN ==> def => [*: 4b], [*: 5b]
+IN ==> abc => [*: 5b], [*: 4b]
+IN ==> def => [*: 5b], [*: 4b]
IN ==>
IN ==> [connected_fhs]
IN ==>
Please sign in to comment.
Something went wrong with that request. Please try again.