lz4-ruby 0.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +81 -0
- data/Rakefile +104 -0
- data/VERSION +1 -0
- data/benchmarking/bench.rb +137 -0
- data/benchmarking/bench_all.sh +5 -0
- data/benchmarking/compressor.rb +71 -0
- data/benchmarking/compressor_lz4.rb +25 -0
- data/benchmarking/compressor_lzo.rb +25 -0
- data/benchmarking/compressor_snappy.rb +25 -0
- data/ext/lz4ruby/extconf.rb +6 -0
- data/ext/lz4ruby/lz4.c +861 -0
- data/ext/lz4ruby/lz4.h +117 -0
- data/ext/lz4ruby/lz4hc.c +671 -0
- data/ext/lz4ruby/lz4hc.h +60 -0
- data/ext/lz4ruby/lz4ruby.c +92 -0
- data/lib/lz4-jruby.rb +3 -0
- data/lib/lz4-ruby.rb +74 -0
- data/lib/lz4ruby.jar +0 -0
- data/pom.xml +71 -0
- data/spec/helper.rb +33 -0
- data/spec/lz4_compressHC_spec.rb +50 -0
- data/spec/lz4_compress_spec.rb +50 -0
- data/src/main/java/com/headius/jruby/lz4/LZ4Internal.java +64 -0
- data/src/main/java/com/headius/jruby/lz4/LZ4Library.java +18 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 374249df236eb445159fdfb1a81f0b62ba57aee6
|
4
|
+
data.tar.gz: bc2f5e4586fab2284aeabdd44888307f27834e0a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 97b8cce382efa5d96a18899b54324e993535a28ac2124d1e63d1bde8049499ebd8e39998818280bcc12792a651bf89f14a15770eed24b515ce13ead33b2c879c
|
7
|
+
data.tar.gz: d6591a08bfa2809638e52db9a1a997023eebd5922a14c3efebc7272ec883c06ff5ed09203aa6e5976845ca8ca05536af45fb763417874ba3000112160dde1978
|
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "rspec"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler"
|
12
|
+
gem "jeweler", "~> 1.8.3"
|
13
|
+
gem "rake-compiler", ">= 0"
|
14
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 KOMIYA Atsushi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
= lz4-ruby
|
2
|
+
|
3
|
+
Ruby bindings for {LZ4}[http://code.google.com/p/lz4/].
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
gem install lz4-ruby
|
8
|
+
|
9
|
+
== Usage
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require 'lz4-ruby'
|
13
|
+
|
14
|
+
# compress (fast)
|
15
|
+
compressed = LZ4::compress("hello, world")
|
16
|
+
|
17
|
+
# compress (high compression)
|
18
|
+
compressed = LZ4::compressHC("hello, world")
|
19
|
+
|
20
|
+
# uncompress
|
21
|
+
uncompressed = LZ4::uncompress(compressed)
|
22
|
+
|
23
|
+
== Benchmark
|
24
|
+
|
25
|
+
Tested on VirtualBox VM : 2-core / 4GB RAM (Host : Core i5-2520M / 8GB RAM).
|
26
|
+
|
27
|
+
=== {enwik8}[http://mattmahoney.net/dc/enwik8.zip]
|
28
|
+
method ratio(bpc) comp.time(ms) uncomp.time(ms)
|
29
|
+
-------------------------------------------------------
|
30
|
+
lz4 4.559 519.25 182.67
|
31
|
+
snappy 4.668 1050.73 257.94
|
32
|
+
lzo 4.279 1000.13 574.77
|
33
|
+
|
34
|
+
== TODO
|
35
|
+
|
36
|
+
* replace calloc() with xalloc() in lz4hc.c
|
37
|
+
* Write API documents.
|
38
|
+
|
39
|
+
== Copyright
|
40
|
+
|
41
|
+
Copyright (c) 2012 KOMIYA Atsushi.
|
42
|
+
See LICENSE.txt for further details.
|
43
|
+
|
44
|
+
== Contributors
|
45
|
+
|
46
|
+
* Charles Oliver Nutter <headius at headius.com>
|
47
|
+
|
48
|
+
== About LZ4
|
49
|
+
|
50
|
+
This Rubygem includes LZ4 codes written by Yann Collet.
|
51
|
+
|
52
|
+
LZ4 - Fast LZ compression algorithm
|
53
|
+
Copyright (C) 2011-2012, Yann Collet.
|
54
|
+
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
55
|
+
|
56
|
+
Redistribution and use in source and binary forms, with or without
|
57
|
+
modification, are permitted provided that the following conditions are
|
58
|
+
met:
|
59
|
+
|
60
|
+
* Redistributions of source code must retain the above copyright
|
61
|
+
notice, this list of conditions and the following disclaimer.
|
62
|
+
* Redistributions in binary form must reproduce the above
|
63
|
+
copyright notice, this list of conditions and the following disclaimer
|
64
|
+
in the documentation and/or other materials provided with the
|
65
|
+
distribution.
|
66
|
+
|
67
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
68
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
69
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
70
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
71
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
72
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
73
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
74
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
75
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
76
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
77
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
78
|
+
|
79
|
+
You can contact the author at :
|
80
|
+
- LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
|
81
|
+
- LZ4 source repository : http://code.google.com/p/lz4/
|
data/Rakefile
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
require 'rake'
|
14
|
+
|
15
|
+
require 'jeweler'
|
16
|
+
jeweler_tasks = Jeweler::Tasks.new do |gem|
|
17
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
18
|
+
gem.name = "lz4-ruby"
|
19
|
+
gem.homepage = "http://github.com/komiya-atsushi/lz4-ruby"
|
20
|
+
gem.license = "MIT"
|
21
|
+
gem.summary = %Q{Ruby bindings for LZ4 (Extremely Fast Compression algorithm).}
|
22
|
+
gem.description = %Q{Ruby bindings for LZ4. LZ4 is a very fast lossless compression algorithm.}
|
23
|
+
gem.email = "komiya.atsushi@gmail.com"
|
24
|
+
gem.authors = ["KOMIYA Atsushi"]
|
25
|
+
gem.extensions = ["ext/lz4ruby/extconf.rb"]
|
26
|
+
|
27
|
+
gem.files.exclude("*.sh")
|
28
|
+
|
29
|
+
gem.files.include("ext/lz4ruby/*.c")
|
30
|
+
gem.files.include("ext/lz4ruby/*.h")
|
31
|
+
|
32
|
+
# dependencies defined in Gemfile
|
33
|
+
end
|
34
|
+
Jeweler::RubygemsDotOrgTasks.new
|
35
|
+
|
36
|
+
$gemspec = jeweler_tasks.gemspec
|
37
|
+
$gemspec.version = jeweler_tasks.jeweler.version
|
38
|
+
|
39
|
+
require 'rspec/core/rake_task'
|
40
|
+
RSpec::Core::RakeTask.new(:spec)
|
41
|
+
|
42
|
+
task :default => :spec
|
43
|
+
|
44
|
+
require 'rdoc/task'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "lz4-ruby #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
53
|
+
|
54
|
+
require 'rake/extensiontask'
|
55
|
+
Rake::ExtensionTask.new("lz4ruby", $gemspec) do |ext|
|
56
|
+
ext.cross_compile = true
|
57
|
+
ext.cross_platform = ["x86-mingw32"]
|
58
|
+
end
|
59
|
+
|
60
|
+
Rake::Task.tasks.each do |task_name|
|
61
|
+
case task_name.to_s
|
62
|
+
when /^native/
|
63
|
+
task_name.prerequisites.unshift('fix_rake_compiler_gemspec_dump')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
task :fix_rake_compiler_gemspec_dump do
|
68
|
+
%w{files extra_rdoc_files test_files}.each do |accessor|
|
69
|
+
$gemspec.send(accessor).instance_eval {
|
70
|
+
@exclude_procs = Array.new
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
task :gems do
|
76
|
+
sh "rake clean build:cross"
|
77
|
+
sh "rake clean build"
|
78
|
+
end
|
79
|
+
|
80
|
+
task "build:cross" => [:modify_gemspec_for_windows, :cross, :build] do
|
81
|
+
file = "pkg/lz4-ruby-#{get_version}.gem"
|
82
|
+
end
|
83
|
+
|
84
|
+
task "build:jruby" => [:modify_gemspec_for_jruby, :compile_jruby, :build]
|
85
|
+
|
86
|
+
task :modify_gemspec_for_windows do
|
87
|
+
$gemspec.extensions = []
|
88
|
+
$gemspec.files.include("lib/?.?/*.so")
|
89
|
+
$gemspec.platform = "x86-mingw32"
|
90
|
+
end
|
91
|
+
|
92
|
+
task :modify_gemspec_for_jruby do
|
93
|
+
$gemspec.extensions = []
|
94
|
+
$gemspec.files.include("lib/*.jar")
|
95
|
+
$gemspec.platform = "java"
|
96
|
+
end
|
97
|
+
|
98
|
+
task :compile_jruby do
|
99
|
+
system 'mvn package'
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_version
|
103
|
+
`cat VERSION`.chomp
|
104
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.0
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
CHUNK_SIZE = 8 << 20
|
5
|
+
NUM_LOOP = 10
|
6
|
+
|
7
|
+
class DevNullIO
|
8
|
+
def write(arg)
|
9
|
+
# Do nothing
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class StringIO
|
14
|
+
def initialize(text)
|
15
|
+
@text = text
|
16
|
+
@len = text.length
|
17
|
+
@pos = 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def read(length)
|
21
|
+
return nil if @pos == @len
|
22
|
+
|
23
|
+
length = @len - @pos if @pos + length > @len
|
24
|
+
|
25
|
+
result = @text[@pos, length]
|
26
|
+
@pos += length
|
27
|
+
|
28
|
+
return result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class CompressorBenchmark
|
33
|
+
USAGE = <<EOS
|
34
|
+
Usage:
|
35
|
+
ruby #{$0} compressor testdata
|
36
|
+
|
37
|
+
Compressor:
|
38
|
+
lz4
|
39
|
+
snappy
|
40
|
+
lzo
|
41
|
+
EOS
|
42
|
+
|
43
|
+
def initialize(args)
|
44
|
+
if args.length != 2
|
45
|
+
puts USAGE
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
|
49
|
+
@signature = args[0]
|
50
|
+
@compressor_rb = "compressor_#{@signature}.rb"
|
51
|
+
|
52
|
+
if !File.file?(@compressor_rb)
|
53
|
+
puts "Error: Compressor '#{@compressor_rb}' is not found."
|
54
|
+
puts USAGE
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
|
58
|
+
@testdata_filename = args[1]
|
59
|
+
if !File.file?(@testdata_filename)
|
60
|
+
puts "Error: testdata `#{@testdata_filename}` is not found."
|
61
|
+
puts USAGE
|
62
|
+
exit 1
|
63
|
+
end
|
64
|
+
|
65
|
+
@compressed_filename = "#{@testdata_filename}.#{@signature}.compressed"
|
66
|
+
|
67
|
+
require "./#{@compressor_rb}"
|
68
|
+
@compressor = create_compressor(CHUNK_SIZE)
|
69
|
+
end
|
70
|
+
|
71
|
+
def setup_compressed
|
72
|
+
`ruby #{@compressor_rb} c #{CHUNK_SIZE} <#{@testdata_filename} >#{@compressed_filename}`
|
73
|
+
end
|
74
|
+
|
75
|
+
def benchmark_compression
|
76
|
+
data = nil
|
77
|
+
File.open(@testdata_filename) do |file|
|
78
|
+
data = file.read(File.size(@testdata_filename))
|
79
|
+
end
|
80
|
+
|
81
|
+
devnull = DevNullIO.new
|
82
|
+
|
83
|
+
# warm up
|
84
|
+
@compressor.compress(StringIO.new(data), devnull)
|
85
|
+
|
86
|
+
result = Benchmark.measure {
|
87
|
+
NUM_LOOP.times { |t| @compressor.compress(StringIO.new(data), devnull) }
|
88
|
+
}
|
89
|
+
|
90
|
+
return result
|
91
|
+
end
|
92
|
+
|
93
|
+
def benchmark_uncompression
|
94
|
+
data = nil
|
95
|
+
File.open(@compressed_filename) do |file|
|
96
|
+
data = file.read(File.size(@compressed_filename))
|
97
|
+
end
|
98
|
+
|
99
|
+
devnull = DevNullIO.new
|
100
|
+
|
101
|
+
# warm up
|
102
|
+
@compressor.uncompress(StringIO.new(data), devnull)
|
103
|
+
|
104
|
+
result = Benchmark.measure {
|
105
|
+
NUM_LOOP.times { |t| @compressor.uncompress(StringIO.new(data), devnull) }
|
106
|
+
}
|
107
|
+
|
108
|
+
return result
|
109
|
+
end
|
110
|
+
|
111
|
+
def show_result(result_comp, result_uncomp)
|
112
|
+
orig_size = File.size(@testdata_filename)
|
113
|
+
comp_size = File.size(@compressed_filename)
|
114
|
+
|
115
|
+
ratio = comp_size * 8.0 / orig_size
|
116
|
+
comp_time = result_comp.real * 1000.0 / NUM_LOOP
|
117
|
+
uncomp_time = result_uncomp.real * 1000.0 / NUM_LOOP
|
118
|
+
|
119
|
+
puts "method\tratio(bpc)\tcomp.time(ms)\tuncomp.time(ms)"
|
120
|
+
puts "-------------------------------------------------------"
|
121
|
+
puts "%s\t%.3f\t\t%.2f\t\t%.2f" % [@signature, ratio, comp_time, uncomp_time]
|
122
|
+
end
|
123
|
+
|
124
|
+
def do_benchmark
|
125
|
+
setup_compressed()
|
126
|
+
|
127
|
+
result_comp = benchmark_compression()
|
128
|
+
result_uncomp = benchmark_uncompression()
|
129
|
+
|
130
|
+
show_result(result_comp, result_uncomp)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if $0 == __FILE__
|
135
|
+
CompressorBenchmark.new(ARGV).do_benchmark
|
136
|
+
end
|
137
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Compressor
|
2
|
+
DEFAULT_CHUNK_SIZE = 8 << 20
|
3
|
+
|
4
|
+
def initialize(chunk_size)
|
5
|
+
if chunk_size == nil
|
6
|
+
@chunk_size = DEFAULT_CHUNK_SIZE
|
7
|
+
else
|
8
|
+
@chunk_size = chunk_size
|
9
|
+
end
|
10
|
+
|
11
|
+
require_libs()
|
12
|
+
end
|
13
|
+
|
14
|
+
def compress(infile, outfile)
|
15
|
+
loop do
|
16
|
+
text = infile.read(@chunk_size)
|
17
|
+
break if text == nil || text.length == 0
|
18
|
+
|
19
|
+
compressed = compress_text(text)
|
20
|
+
comp_size = compressed.length
|
21
|
+
|
22
|
+
outfile.write([comp_size].pack("L"))
|
23
|
+
outfile.write(compressed)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def uncompress(infile, outfile)
|
28
|
+
loop do
|
29
|
+
comp_size = infile.read(4)
|
30
|
+
break if comp_size == nil || comp_size.length == 0
|
31
|
+
|
32
|
+
comp_size = comp_size.unpack("L")[0]
|
33
|
+
compressed = infile.read(comp_size)
|
34
|
+
|
35
|
+
text = uncompress_text(compressed)
|
36
|
+
|
37
|
+
outfile.write(text)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.unit_driver()
|
42
|
+
if !(ARGV.length == 1) && !(ARGV.length == 2 && ARGV[0] == 'c')
|
43
|
+
puts <<EOS
|
44
|
+
Compress:
|
45
|
+
./#{$0} c <infile >outfile
|
46
|
+
|
47
|
+
Uncompress:
|
48
|
+
./#{$0} u <infile >outfile
|
49
|
+
EOS
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
|
53
|
+
require 'rubygems'
|
54
|
+
|
55
|
+
case ARGV[0]
|
56
|
+
when 'c'
|
57
|
+
chunk_size = nil
|
58
|
+
chunk_size = ARGV[1].to_i if ARGV.length == 2
|
59
|
+
compressor = create_compressor(chunk_size)
|
60
|
+
compressor.compress($stdin, $stdout)
|
61
|
+
|
62
|
+
when 'u'
|
63
|
+
compressor = create_compressor(nil)
|
64
|
+
compressor.uncompress($stdin, $stdout)
|
65
|
+
|
66
|
+
else
|
67
|
+
puts "Error: illegal argument '#{ARGV[0]}'"
|
68
|
+
exit 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|