hbase-jruby 0.6.3-java → 0.6.4-java

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: 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