hbase-jruby 0.6.3-java → 0.6.4-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0654a082ed7102051b33a0d27f9b317870f59eb2
4
- data.tar.gz: a050c546803000e36f4daadc511beff5c3b24b51
3
+ metadata.gz: f36f9ad6226b500c087ad5a8ffc9f294c738752e
4
+ data.tar.gz: 23ac26035d0054188538e115d899c191dd803776
5
5
  SHA512:
6
- metadata.gz: a8bb69c1d2909ad7ddff0062087eedf78552dbe75fbfcb9d95f5ad4e3c0e6a28b77b1a0529e4426aed8fab6ac267568a7d085938933419bd1354b8dff5285871
7
- data.tar.gz: b0b872f8559795f34b2b546f55e7386f3763e7b2a14d7de61a7909a8ed3de68e7f606534f37ae156bb3f823fbca482c29dd13412cfa28a9cfb62b0caa4c63762
6
+ metadata.gz: cb25e98c711400af4e3eda1f91efbc0ca2a145f0c213384ea7da2bb45d4b98f6511381dee30c0a606faf9c1f10948aff5996d6c447cfc0acb41d98d71cd9349c
7
+ data.tar.gz: 58a59bf73bf759718bd58063af461cee14ece10de17cd40634b81dbf26a6406fa3d8dc608a842fde314bb42a74a537c9965e3073edb368e12f34b6961e1445dc
@@ -1,6 +1,29 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 0.6.4
5
+ -----
6
+
7
+ ### Performance improvement (experimental)
8
+
9
+ `HBase::Table` instance can be set up to cache the interpretations of the
10
+ column keys using thread-locals which can lead to 3-times faster Put
11
+ generation in tight loops.
12
+
13
+ ```ruby
14
+ table = hbase[:my_table, cache: true]
15
+ # ...
16
+ table.close
17
+ ```
18
+
19
+ However, the option is off by default because of the following issues:
20
+
21
+ 1. You should not use it with the tables with unlimited number of columns.
22
+ 2. Caching does not keep track of the updates of the schema. If you change the
23
+ schema of an `HBase` object after you created an `HBase::Table` object with
24
+ the cache turned on from it, the object may hold stale information on the
25
+ types of the columns. `HBase::Table#close` method will clean up the cache.
26
+
4
27
  0.6.3
5
28
  -----
6
29
 
@@ -9,6 +9,7 @@ class HBase
9
9
  attr_reader :config, :schema
10
10
 
11
11
  include Admin
12
+ include HBase::Util
12
13
 
13
14
  # @overload HBase.log4j=(filename)
14
15
  # Configure Log4j logging with the given file
@@ -99,7 +100,7 @@ class HBase
99
100
  end
100
101
  end
101
102
 
102
- # Closes HTablePool and connection
103
+ # Closes the connection, and clean up thread-local cache
103
104
  # @return [nil]
104
105
  def close
105
106
  @mutex.synchronize do
@@ -117,6 +118,10 @@ class HBase
117
118
  end if use_table_pool?
118
119
  end
119
120
  end
121
+
122
+ thread_local.delete self
123
+
124
+ nil
120
125
  end
121
126
 
122
127
  # Returns whether if the connection is closed
@@ -128,25 +133,25 @@ class HBase
128
133
  # Returns the list of HBase::Table instances
129
134
  # @return [Array<HBase::Table>]
130
135
  def tables
131
- check_closed
132
136
  table_names.map { |tn| table(tn) }
133
137
  end
134
138
 
135
139
  # Returns the list of table names
136
140
  # @return [Array<String>]
137
141
  def table_names
138
- check_closed
139
142
  with_admin { |admin| admin.list_tables.map(&:name_as_string) }
140
143
  end
141
144
  alias list table_names
142
145
 
143
146
  # Creates an HBase::Table instance for the specified name
144
147
  # @param [#to_s] table_name The name of the table
148
+ # @param [Hash] opts Options
149
+ # @option opts [Boolean] :cache Use thread-local cache (default: false)
145
150
  # @return [HBase::Table]
146
- def table table_name
151
+ def table table_name, opts = {}
147
152
  check_closed
148
153
 
149
- ht = HBase::Table.send :new, self, @config, table_name
154
+ ht = HBase::Table.send :new, self, @config, table_name, opts[:cache]
150
155
 
151
156
  if block_given?
152
157
  yield ht
@@ -21,23 +21,16 @@ class Table
21
21
  check_closed
22
22
 
23
23
  # [:hbase_jruby][HBase connection][Table name]
24
- local_vars = Thread.current[:hbase_jruby] ||= {}
25
- unless local_htables = local_vars[@hbase]
26
- local_htables = local_vars[@hbase] = {}
27
- end
28
- local_htables[@name] ||= @hbase.send :get_htable, @name
24
+ thread_local(@hbase, @name_sym)[:htable] ||= @hbase.send(:get_htable, @name)
29
25
  end
30
26
 
31
- # Return HTable instance back to the table pool.
27
+ # Clean up thread-locals
32
28
  # Generally this is not required unless you use unlimited number of threads
33
29
  # @return [nil]
34
30
  def close
35
- check_closed
36
-
37
- (t = Thread.current[:hbase_jruby]) &&
38
- (t = t[@hbase]) &&
39
- (t = t.delete @name) &&
40
- t.close
31
+ hash = thread_local(@hbase).delete(@name_sym)
32
+ hash[:htable].close if hash && hash[:htable]
33
+ nil
41
34
  end
42
35
 
43
36
  # Returns whether if the connection is closed
@@ -320,13 +313,23 @@ class Table
320
313
  @hbase.schema.lookup_and_parse @name_sym, col, expect_cq
321
314
  end
322
315
 
316
+ # @private
317
+ module ThreadLocalCache
318
+ def lookup_and_parse col, expect_cq
319
+ thread_local(@hbase, @name_sym, :columns)[col] ||=
320
+ @hbase.schema.lookup_and_parse(@name_sym, col, expect_cq)
321
+ end
322
+ end
323
+
323
324
  private
324
- def initialize hbase, config, name
325
+ def initialize hbase, config, name, cache
325
326
  @hbase = hbase
326
327
  @config = config
327
328
  @name = name.to_s
328
329
  @name_sym = name.to_sym
329
330
  @mutation = Mutation.new(self)
331
+
332
+ extend ThreadLocalCache if cache
330
333
  end
331
334
 
332
335
  def check_closed
@@ -27,6 +27,8 @@ class Mutation
27
27
  put.add cf, cq, Util.to_typed_bytes(t, v)
28
28
  end unless v.nil?
29
29
  end
30
+ when String
31
+ put.add cf, cq, val.to_java_bytes
30
32
  else
31
33
  put.add cf, cq, Util.to_typed_bytes(type, val)
32
34
  end
@@ -194,6 +194,16 @@ private
194
194
  raise ArgumentError, "Invalid time format"
195
195
  end
196
196
  end
197
+
198
+ # XXX Why am I doing this instead of using inject (reduce)?
199
+ # Because inject is around 25% slower, and this method is used in tight loops
200
+ def thread_local key1 = nil, key2 = nil, key3 = nil
201
+ obj = Thread.current[:hbase_jruby] ||= {}
202
+ obj = obj[key1] ||= {} if key1
203
+ obj = obj[key2] ||= {} if key2
204
+ obj = obj[key3] ||= {} if key3
205
+ obj
206
+ end
197
207
  end#Util
198
208
  end#HBase
199
209
 
@@ -1,5 +1,5 @@
1
1
  class HBase
2
2
  module JRuby
3
- VERSION = '0.6.3'
3
+ VERSION = '0.6.4'
4
4
  end
5
5
  end
@@ -26,7 +26,7 @@ class TestHBase < TestHBaseJRubyBase
26
26
  table.exists?
27
27
  assert @hbase.list.is_a?(Array)
28
28
 
29
- assert_equal table.htable, Thread.current[:hbase_jruby][@hbase][TABLE]
29
+ assert_equal table.htable, Thread.current[:hbase_jruby][@hbase][TABLE.to_sym][:htable]
30
30
 
31
31
  assert !@hbase.closed?
32
32
  assert !table.closed?
@@ -51,7 +51,7 @@ class TestHBase < TestHBaseJRubyBase
51
51
  # Reconnect and check
52
52
  @hbase = connect
53
53
  table = @hbase[TABLE]
54
- assert_equal table.htable, Thread.current[:hbase_jruby][@hbase][TABLE]
54
+ assert_equal table.htable, Thread.current[:hbase_jruby][@hbase][TABLE.to_sym][:htable]
55
55
 
56
56
  # FIXME: Connection is closed, we have to update @table object
57
57
  @table = @hbase.table(TABLE)
@@ -83,9 +83,9 @@ class TestHBase < TestHBaseJRubyBase
83
83
  table = hbase2[TABLE]
84
84
  assert_nil Thread.current[:hbase_jruby][hbase2]
85
85
 
86
- table.htable
86
+ ht = table.htable
87
87
  # Thread-local htable cache has now been created
88
- assert Thread.current[:hbase_jruby][hbase2][TABLE]
88
+ assert_equal ht, Thread.current[:hbase_jruby][hbase2][TABLE.to_sym][:htable]
89
89
 
90
90
  sleeping = {}
91
91
  mutex = Mutex.new
@@ -99,8 +99,8 @@ class TestHBase < TestHBaseJRubyBase
99
99
  sleep 0.1 while mutex.synchronize { sleeping.length } < 4
100
100
  threads.each do |t|
101
101
  assert t[:htable]
102
- assert t[:hbase_jruby][hbase2][TABLE]
103
- assert_equal t[:htable], t[:hbase_jruby][hbase2][TABLE]
102
+ assert t[:hbase_jruby][hbase2][TABLE.to_sym]
103
+ assert_equal t[:htable], t[:hbase_jruby][hbase2][TABLE.to_sym][:htable]
104
104
 
105
105
  t.kill
106
106
  end
@@ -410,7 +410,7 @@ class TestTable < TestHBaseJRubyBase
410
410
 
411
411
  assert_equal true, @table.check(rk, a => 100).delete(c, ts, (ts - 2000).to_i, 'cf2')
412
412
  assert_equal 1, @table.versions(:all).get(rk).to_H[:c].length
413
- assert_equal (ts - 1000).to_i, @table.versions(:all).get(rk).to_H[:c].keys.first / 1000
413
+ assert_equal((ts - 1000).to_i, @table.versions(:all).get(rk).to_H[:c].keys.first / 1000)
414
414
  assert_equal nil, @table.get(rk)[d]
415
415
 
416
416
  assert_equal true, @table.check(rk, a => 100).delete
@@ -541,5 +541,19 @@ class TestTable < TestHBaseJRubyBase
541
541
  assert e.java_exception.is_a?(java.lang.Exception)
542
542
  end
543
543
  end
544
+
545
+ def test_thread_local_cache
546
+ cached = @hbase[TABLE, :cache => true]
547
+ not_cached = @hbase[TABLE]
548
+
549
+ cached.put next_rowkey, 'cf1:abc' => 100
550
+ not_cached.put next_rowkey, 'cf1:def' => 100
551
+
552
+ assert_equal ['cf1:abc'], Thread.current[:hbase_jruby][@hbase][TABLE.to_sym][:columns].keys
553
+ cached.close
554
+
555
+ # FIXME closing not_cached will also remove the cache
556
+ assert_nil Thread.current[:hbase_jruby][@hbase][TABLE.to_sym]
557
+ end
544
558
  end
545
559
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hbase-jruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.4
5
5
  platform: java
6
6
  authors:
7
7
  - Junegunn Choi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-05 00:00:00.000000000 Z
11
+ date: 2014-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit