< :the previous in number
^ :the list in numerical order
> :the next in number
P :the previous aricle (the previous thread)
N :the next (in thread)
|<:the previous thread
>|:the next thread
^ :the parent (reply-to)
_:the child (an article replying to this)
>:the elder article having the same parent
<:the youger article having the same parent
---:split window and show thread lists
| :split window (vertically) and show thread lists
~ :close the thread frame
.:the index
..:the index of indices
--nextPart20763057.7iusmhGbMz
Content-Type: multipart/mixed;
boundary="Boundary-01=_9CMkBOMZk3M6FPy"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
--Boundary-01=_9CMkBOMZk3M6FPy
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
On Thursday 04 November 2004 07:28, Florian Gross wrote:
> Sean Russell wrote:
> > I was playing around with the SyncEnumerator from Ruby 1.8, and
> > noticed that it was taking a long time to iterate over elements.
=2E..
> > Is there any reason why I shouldn't submit this as an RCR to replace
> > SyncEnumerator?
>
> I wonder how an implementation using .zip with a block would compare? Or
> would that not do the same thing?
#zip ends up being slower in construction (because we have to find the larg=
est=20
array) and faster in iteration. It is also more elegant, and it is now my=
=20
preferred version.
139 % ruby synctest.rb =
=20
~/Work/Sync
Construction
SyncEnumerator1: 0.041632
SyncEnumerator2: 0.138032
Starting SyncEnumerator1
=2E........................................................................=
=2E........................................................................=
=2E.............
26 shold be 26 :: Time: 0.132563
Starting SyncEnumerator2
=2E........................................................................=
=2E........................................................................=
=2E.............
26 shold be 26 :: Time: 0.041874
Here's the test including the original SyncEnumerator; I had to scale down =
the=20
repetitions because the original is about three orders of magnitude slower=
=20
than either of the new versions:
152 % ruby synctest.rb =
=20
~/Work/Sync
Construction
SyncEnumerator: 0.245202
SyncEnumerator1: 0.000343
SyncEnumerator2: 0.001459
Starting SyncEnumerator
=2E........................................................................=
=2E......
26 shold be 26 :: Time: 15.135305
Starting SyncEnumerator1
=2E........................................................................=
=2E......
26 shold be 26 :: Time: 0.025891
Starting SyncEnumerator2
=2E........................................................................=
=2E......
26 shold be 26 :: Time: 0.017458
I'm attaching the sources.
* mysync.rb defines SyncEnumerator1 and SyncEnumerator2; #2 is implemented=
=20
with #zip, and is the version I'm proposing replace the original=20
SyncEnumerator.
* mysynctest.rb contains unit tests for both version #1 and #2
* benchmark.rb contains the benchmarks above.
=2D-=20
### SER =20
### Deutsch|Esperanto|Francaise|Linux|XML|Java|Ruby|Aikido
### http://www.germane-software.com/~ser jabber.com:ser ICQ:83578737=20
### GPG: http://www.germane-software.com/~ser/Security/ser_public.gpg
--Boundary-01=_9CMkBOMZk3M6FPy
Content-Type: application/x-ruby;
name="benchmark.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="benchmark.rb"
require 'generator'
require 'mysync'
I = 100
N = 80
a = %w{ a b c d e f g h i j k l m n o p q r s t u v w x y z }
b = a.reverse
c = %w{ 1 2 3 4 5 6 7 8 9 10 11 12 }
d = c.reverse
puts "Construction"
#classes = [ SyncEnumerator1, SyncEnumerator2 ]
classes = [ SyncEnumerator, SyncEnumerator1, SyncEnumerator2 ]
classes.each { |klass|
t=Time.now; I.times { klass.new( a,b,c,d ) }; puts "#{klass.name}: #{Time.now-t}"
}
GC.start
for sync in classes.collect { |k| k.new( a, b, c, d ) }
puts "Starting #{sync.class.name}"
time = Time.now
count = 0
N.times { sync.each { |x,y| count += 1 } ; print "." ; STDOUT.flush }
time = Time.now - time
puts "\n#{count / N} shold be #{a.size} :: Time: #{time}"
GC.start
end
--Boundary-01=_9CMkBOMZk3M6FPy
Content-Type: application/x-ruby;
name="mysynctest.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="mysynctest.rb"
require 'mysync'
require 'test/unit'
class SyncTest < Test::Unit::TestCase
def test_one
a = %w{ a b c d e f g h i j k l m n o p q r s t u v w x y z }
b = %w{ 1 2 3 4 5 6 7 8 9 10 11 12 }
c = [ 1,2,3,4,5,6,7,9,9,10,11,12,13,14,15 ]
x = []
y = []
z = []
sync = SyncEnumerator1.new( a, b, c ).each { |m,n,o|
x << m
y << n
z << o
}
y.compact! # Get rid of end nils
z.compact!
assert_equal( a, x )
assert_equal( b, y )
assert_equal( c, z )
x = []
y = []
z = []
sync = SyncEnumerator1.new( c, b, a ).each { |m,n,o|
z << m
y << n
x << o
}
y.compact! # Get rid of end nils
z.compact!
assert_equal( a, x )
assert_equal( b, y )
assert_equal( c, z )
end
def test_two
a = %w{ a b c d e f g h i j k l m n o p q r s t u v w x y z }
b = %w{ 1 2 3 4 5 6 7 8 9 10 11 12 }
c = [ 1,2,3,4,5,6,7,9,9,10,11,12,13,14,15 ]
x = []
y = []
z = []
sync = SyncEnumerator2.new( a, b, c ).each { |m,n,o|
x << m
y << n
z << o
}
y.compact! # Get rid of end nils
z.compact!
assert_equal( a, x )
assert_equal( b, y )
assert_equal( c, z )
x = []
y = []
z = []
sync = SyncEnumerator2.new( c, b, a ).each { |m,n,o|
z << m
y << n
x << o
}
y.compact! # Get rid of end nils
z.compact!
assert_equal( a, x )
assert_equal( b, y )
assert_equal( c, z )
end
end
--Boundary-01=_9CMkBOMZk3M6FPy
Content-Type: application/x-ruby;
name="mysync.rb"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="mysync.rb"
class SyncEnumerator1
include Enumerable
# Creates a new SyncEnumerator which enumerates rows of given
# Enumerable objects.
def initialize(*enums)
@gens = enums
end
# Returns the number of enumerated Enumerable objects, i.e. the size
# of each row.
def size
@gens.size
end
# Returns the number of enumerated Enumerable objects, i.e. the size
# of each row.
def length
@gens.length
end
# Enumerates rows of the Enumerable objects.
def each
count = 0
maxsize = 0
@gens.each { |g| maxsize = g.size > maxsize ? g.size : maxsize }
until count >= maxsize
yield @gens.map { |g| g[count] }
count += 1
end
self
end
end
class SyncEnumerator2
include Enumerable
# Creates a new SyncEnumerator which enumerates rows of given
# Enumerable objects.
def initialize(*enums)
@gens = enums
@biggest = @gens[0]
@gens.each {|x| @biggest = x if x.size > @biggest.size }
end
# Returns the number of enumerated Enumerable objects, i.e. the size
# of each row.
def size
@gens.size
end
# Returns the number of enumerated Enumerable objects, i.e. the size
# of each row.
def length
@gens.length
end
# Enumerates rows of the Enumerable objects.
def each
@biggest.zip( *@gens ) {|a|
yield *a[1..-1]
}
self
end
end
--Boundary-01=_9CMkBOMZk3M6FPy--
--nextPart20763057.7iusmhGbMz
Content-Type: application/pgp-signature
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)
iD8DBQBBkMDIP0KxygnleI8RAipvAJ9Cy3+1qPXCJ0bBPbLc0SbU9FVUrgCfX/Ak
hdqPuCBfYufGj+kuA1PR26A=
=ofkU
-----END PGP SIGNATURE-----
--nextPart20763057.7iusmhGbMz--