em-zipper 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64af8eac1c0ad6532476956a5b9852c8cc6d8acf
4
- data.tar.gz: 16ef90ab41a5ee6416f5ac4b0979aa4b6ef71f21
3
+ metadata.gz: 9cb4c9228359aa7f2d20d70f6ba45d8065fe3a7d
4
+ data.tar.gz: b2b4bdbbe95c3b5f97864e3cdf63999c087c1543
5
5
  SHA512:
6
- metadata.gz: ece25c89c5c737918b9bc3a43c0aada19034166523091441d3c52e1c5ebde846ba35d9e21ffeefe1f3ad0b18c07cb85f80a1d95301cf9ff7946f415851ce36e2
7
- data.tar.gz: 08fa21a4d870487480b779d616fdcd0cf265e27d27aaa526d0fc827466144110a169d7871558c6d8b0141deaf0b35f13e88b9060d7dd0ac4504eb55392daafa2
6
+ metadata.gz: 2f853b18fc71e141fabacba3f2134c8af4e2a1ddb20c0801291f065008930aaeb9f8eb73845b4242923803e5475c016e1cb1eb826cb553cbfa9bc6d7dd523ec6
7
+ data.tar.gz: d2b930387a4d820a79f8f7fcc67a23150722fef8b280680354a99a0605fa17792d1a4ff989387212eed6ac65aea2aa55f4b399ea079efa4f0c8609a430c73a88
@@ -0,0 +1,105 @@
1
+ $: << File.expand_path('../lib', __FILE__)
2
+ require 'rubygems'
3
+ require "benchmark"
4
+ require 'em-zipper'
5
+ require 'net/http'
6
+
7
+
8
+ sites = %w(http://s3.amazonaws.com/ping-em-assets/sample1.txt http://s3.amazonaws.com/ping-em-assets/sample2.txt)
9
+ files = %w(sample1.txt sample2.txt).map do |file_name|
10
+ File.join(File.expand_path("./examples/files"), file_name)
11
+ end
12
+
13
+ n = 10
14
+ @count = 0
15
+
16
+ def em_zipper(collection, n)
17
+ zip = EM::Zipper.new(collection, StringIO.new).zip!
18
+ zip.callback do |io|
19
+ io.close
20
+ @count = @count + 1
21
+ EM.stop if @count == n
22
+ end
23
+ end
24
+
25
+ def rubyzip(collection, n)
26
+ ::Zip::ZipOutputStream.write_buffer do |zip|
27
+ collection.each do |file_path|
28
+ zip.put_next_entry(File.basename(file_path))
29
+
30
+ begin
31
+ if file_path.match(/\Ahttps?:\/\//)
32
+ uri = URI file_path
33
+ Net::HTTP.start(uri.host, uri.port) do |http|
34
+ request = Net::HTTP::Get.new uri
35
+
36
+ http.request request do |response|
37
+ response.read_body { |chunk| zip << chunk }
38
+ end
39
+ end
40
+ else
41
+ file = File.open file_path
42
+ while chunk = file.read_nonblock(16384)
43
+ zip << chunk
44
+ end
45
+ end
46
+ rescue EOFError
47
+ # /
48
+ ensure
49
+ file && file.close
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+
56
+ # //
57
+
58
+
59
+ marks = Benchmark.benchmark do |b|
60
+ b.report("[file] em-zipper") do
61
+ @count = 0
62
+
63
+ EM.run do
64
+ n.times do
65
+ EM.next_tick { em_zipper(files, n) }
66
+ end
67
+ end
68
+ end
69
+
70
+ b.report('[file] rubyzip') do
71
+ n.times do
72
+ rubyzip(files, n)
73
+ end
74
+ end
75
+
76
+ b.report("[net] em-zipper") do
77
+ @count = 0
78
+
79
+ EM.run do
80
+ n.times do
81
+ EM.next_tick { em_zipper(sites, n) }
82
+ end
83
+ end
84
+ end
85
+
86
+ b.report('[net] rubyzip') do
87
+ n.times do
88
+ rubyzip(sites, n)
89
+ end
90
+ end
91
+ end
92
+
93
+ puts marks
94
+
95
+ # //
96
+ #
97
+ # [file] em-zipper 2.780000 0.040000 2.820000 ( 2.829317)
98
+ # [file] rubyzip 2.690000 0.030000 2.720000 ( 2.740578)
99
+ # [net] em-zipper 3.060000 0.150000 3.210000 ( 5.076801)
100
+ # [net] rubyzip 3.020000 0.090000 3.110000 ( 6.962918)
101
+ # 2.780000 0.040000 2.820000 ( 2.829317)
102
+ # 2.690000 0.030000 2.720000 ( 2.740578)
103
+ # 3.060000 0.150000 3.210000 ( 5.076801)
104
+ # 3.020000 0.090000 3.110000 ( 6.962918)
105
+
@@ -13,7 +13,13 @@ end
13
13
 
14
14
  Tach.meter(10) do
15
15
  tach('[file] em-zipper') do |n|
16
- em_zipper files, n
16
+ @count = 0
17
+
18
+ EM.run do
19
+ n.times do |i|
20
+ EM.next_tick { em_zipper files, n }
21
+ end
22
+ end
17
23
  end
18
24
 
19
25
  tach('[file] rubyzip') do |n|
@@ -21,7 +27,13 @@ Tach.meter(10) do
21
27
  end
22
28
 
23
29
  tach('[net] em-zipper') do |n|
24
- em_zipper sites, n
30
+ @count = 0
31
+
32
+ EM.run do
33
+ n.times do |i|
34
+ EM.next_tick { em_zipper files, n }
35
+ end
36
+ end
25
37
  end
26
38
 
27
39
  tach('[net] rubyzip') do |n|
@@ -30,21 +42,11 @@ Tach.meter(10) do
30
42
 
31
43
 
32
44
  def em_zipper(collection, n)
33
- EventMachine.run do
34
- count = 0
35
-
36
- em_zipper = proc do
37
- zip = EM::Zipper.new(collection, StringIO.new).zip!
38
- zip.callback do |io|
39
- io.close
40
- count = count + 1
41
- EM.stop if count == n
42
- end
43
- end
44
-
45
- n.times do |i|
46
- EM.next_tick(&em_zipper)
47
- end
45
+ zip = EM::Zipper.new(collection, StringIO.new).zip!
46
+ zip.callback do |io|
47
+ io.close
48
+ @count = @count + 1
49
+ EM.stop if @count == n
48
50
  end
49
51
  end
50
52
 
@@ -85,27 +87,27 @@ end
85
87
  # File sizes 1.5mb, 503kb
86
88
  #
87
89
  # x10
88
- # +------------------+----------+
89
- # | tach | total |
90
- # +------------------+----------+
91
- # | [file] em-zipper | 2.849514 |
92
- # +------------------+----------+
93
- # | [net] em-zipper | 3.646211 |
94
- # +------------------+----------+
95
- # | [net] rubyzip | 5.765788 |
96
- # +------------------+----------+
97
- # | [file] rubyzip | 9.334782 |
98
- # +------------------+----------+
90
+ # +------------------+-----------+
91
+ # | tach | total |
92
+ # +------------------+-----------+
93
+ # | [net] em-zipper | 2.727529 |
94
+ # +------------------+-----------+
95
+ # | [file] em-zipper | 2.753560 |
96
+ # +------------------+-----------+
97
+ # | [file] rubyzip | 8.035955 |
98
+ # +------------------+-----------+
99
+ # | [net] rubyzip | 10.780907 |
100
+ # +------------------+-----------+
99
101
  #
100
102
  # x100
101
103
  # +------------------+-----------+
102
104
  # | tach | total |
103
105
  # +------------------+-----------+
104
- # | [file] em-zipper | 27.344414 |
106
+ # | [file] em-zipper | 27.435623 |
105
107
  # +------------------+-----------+
106
- # | [net] em-zipper | 48.246017 |
108
+ # | [net] em-zipper | 27.858313 |
107
109
  # +------------------+-----------+
108
- # | [net] rubyzip | 60.066137 |
110
+ # | [net] rubyzip | 58.306401 |
109
111
  # +------------------+-----------+
110
- # | [file] rubyzip | 66.197528 |
112
+ # | [file] rubyzip | 60.937767 |
111
113
  # +------------------+-----------+
data/lib/em-zipper.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'eventmachine'
2
2
 
3
3
  require 'em-zipper/base'
4
+ require 'em-zipper/entry'
5
+ require 'em-zipper/chunks'
4
6
  require 'em-zipper/zip_output_stream'
5
7
  require 'em-zipper/stream_io'
6
8
 
@@ -11,11 +11,14 @@ module EventMachine
11
11
  @files = files
12
12
  @zos = zos
13
13
  @fqueue = EM::Queue.new
14
+ @count = 0
14
15
  end
15
16
 
16
17
  def zip!
17
- files.each { |file_path| fqueue.push file_path }
18
- fqueue.pop(&next_entry_non_block)
18
+ files.each do |file_path|
19
+ EM.next_tick { chunk_data(file_path) }
20
+ end
21
+ fqueue.pop(&write_entry) # begin queue, first file to chunk will be issued this call
19
22
 
20
23
  self # ...new(..., ...).zip!
21
24
  end
@@ -23,65 +26,34 @@ module EventMachine
23
26
 
24
27
  private
25
28
 
26
- def file_name(file_path)
27
- File.basename file_path
28
- end
29
-
30
29
  def close_zos
31
30
  zos.close if zos.io.is_a?(File) # close the io if it's a file
32
- succeed zos.close_buffer # return the zos
31
+ succeed zos.close_buffer # return the zos
33
32
  end
34
33
 
35
- def next_entry_non_block
36
- proc do |file_path|
37
- cqueue = EM::Queue.new
38
- chunky = proc do |chunk|
39
- zos << chunk
34
+ def write_entry
35
+ proc do |args|
36
+ file_path = args[0]
37
+ q = args[1]
38
+
39
+ entry = Entry.new(file_path, q, zos).write!
40
+ entry.callback do
41
+ @count = @count + 1
40
42
 
41
- if cqueue.empty?
42
- close_zos and return if fqueue.empty?
43
- EM.next_tick { fqueue.pop(&next_entry_non_block) }
43
+ if files.size == @count
44
+ close_zos
44
45
  else
45
- EM.next_tick { cqueue.pop(&chunky) }
46
+ EM.next_tick { fqueue.pop(&write_entry) }
46
47
  end
47
48
  end
48
-
49
- defer = EM::DefaultDeferrable.new
50
- defer.callback do
51
- # begin the entry when we have all the data
52
- new_entry = ::Zip::ZipEntry.new '-', file_name(file_path)
53
- zos.put_next_entry(new_entry)
54
-
55
- EM.next_tick { cqueue.pop(&chunky) } if cqueue.size > 0
56
- end
57
- defer.errback { puts 'error' }
58
-
59
- _chunk_method = file_path.match(/\Ahttps?:\/\//) ? :chunk_http : :chunk_file
60
- __send__ _chunk_method, file_path, cqueue, defer
61
49
  end
62
50
  end
63
51
 
64
- def chunk_file(file_path, q, d)
65
- file = File.open file_path
66
-
67
- fr = proc do
68
- begin
69
- q.push file.read_nonblock(16384)
70
- EM.next_tick(&fr)
71
- rescue EOFError
72
- file.close
73
- EM.next_tick { d.succeed }
74
- end
52
+ def chunk_data(file_path)
53
+ chunks = Chunks.new(file_path).chop!
54
+ chunks.callback do |chunk_q|
55
+ EM.next_tick { fqueue.push [file_path, chunk_q] }
75
56
  end
76
-
77
- EM.next_tick(&fr)
78
- end
79
-
80
- def chunk_http(uri, q, d)
81
- http = EventMachine::HttpRequest.new(uri).get
82
- http.errback { EM.next_tick { d.fail } }
83
- http.callback { EM.next_tick { d.succeed } }
84
- http.stream { |chunk| q.push chunk }
85
57
  end
86
58
  end
87
59
  end
@@ -0,0 +1,47 @@
1
+ module EventMachine
2
+ module Zipper
3
+ class Chunks
4
+ include EventMachine::Deferrable
5
+
6
+ attr_reader :file_path, :q
7
+
8
+ def initialize(file_path)
9
+ @file_path = file_path
10
+ @q = EM::Queue.new
11
+ end
12
+
13
+ def chop!
14
+ _chunk_method = file_path.match(/\Ahttps?:\/\//) ? :chunk_http : :chunk_file
15
+ __send__ _chunk_method
16
+
17
+ self
18
+ end
19
+
20
+
21
+ private
22
+
23
+ def chunk_file
24
+ file = File.open file_path
25
+
26
+ fr = proc do
27
+ begin
28
+ q.push file.read_nonblock(16384)
29
+ EM.next_tick(&fr)
30
+ rescue EOFError
31
+ file.close
32
+ succeed(q)
33
+ end
34
+ end
35
+
36
+ EM.next_tick(&fr)
37
+ end
38
+
39
+ def chunk_http
40
+ http = EventMachine::HttpRequest.new(file_path).get
41
+ http.errback { fail }
42
+ http.callback { succeed(q) }
43
+ http.stream { |chunk| q.push chunk }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,46 @@
1
+ module EventMachine
2
+ module Zipper
3
+ class Entry
4
+ include EventMachine::Deferrable
5
+
6
+ attr_reader :file_path, :chunks, :out
7
+
8
+ def initialize(file_path, chunks, out)
9
+ @file_path = file_path
10
+ @chunks = chunks
11
+ @out = out
12
+ end
13
+
14
+ def write!
15
+ create_entry
16
+ EM.next_tick { chunks.pop(&write_chunks) }
17
+
18
+ self
19
+ end
20
+
21
+
22
+ private
23
+
24
+ def write_chunks
25
+ proc do |chunk|
26
+ out << chunk
27
+
28
+ if chunks.empty?
29
+ EM.next_tick { succeed }
30
+ else
31
+ EM.next_tick { chunks.pop(&write_chunks) }
32
+ end
33
+ end
34
+ end
35
+
36
+ def file_name
37
+ @file_namem ||= File.basename file_path
38
+ end
39
+
40
+ def create_entry
41
+ new_entry = ::Zip::ZipEntry.new '-', file_name
42
+ out.put_next_entry(new_entry)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,5 +1,5 @@
1
1
  module EventMachine
2
2
  module Zipper
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-zipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yung Hwa Kwon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-16 00:00:00.000000000 Z
11
+ date: 2013-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -63,6 +63,7 @@ files:
63
63
  - .ruby-version
64
64
  - Gemfile
65
65
  - Gemfile.lock
66
+ - benchmarkz/em-zipper-bm.rb
66
67
  - benchmarkz/em-zipper.rb
67
68
  - em-zipper.gemspec
68
69
  - examples/async_sinatra.md
@@ -72,6 +73,8 @@ files:
72
73
  - examples/io.rb
73
74
  - lib/em-zipper.rb
74
75
  - lib/em-zipper/base.rb
76
+ - lib/em-zipper/chunks.rb
77
+ - lib/em-zipper/entry.rb
75
78
  - lib/em-zipper/stream_io.rb
76
79
  - lib/em-zipper/version.rb
77
80
  - lib/em-zipper/zip_output_stream.rb