liveh2o / active_remote

Active Remote provides Active Record-like object-relational mapping over RPC. It's Active Record for your platform.
MIT License
63 stars 23 forks source link

Update to ActiveModel 5.2 #68

Closed liveh2o closed 4 years ago

liveh2o commented 5 years ago

ActiveModel 5.2 pulls in some attribute management from ActiveRecord which means a lot of code pulled in from ActiveAttr can be removed. Compatibility with ActiveModel/ActiveRecord means some attribute methods have been removed (i.e., read_attribute, public write_attribute) in favor of Rails patterns. It also brings a significant speed boost: 2.4x faster initialization, 6.6x faster instantiation in MRI, and 3x faster initialization, 12x faster instantiation in JRuby.

Ruby 2.5.3

# Rails 4.2

Warming up --------------------------------------
          initialize     1.335k i/100ms
         instantiate     3.611k i/100ms
     init attributes     1.429k i/100ms
     inst attributes     3.519k i/100ms
Calculating -------------------------------------
          initialize     14.808k (±11.0%) i/s -    292.365k in  20.033342s
         instantiate     39.668k (±14.8%) i/s -    772.754k in  20.083307s
     init attributes     14.555k (±10.8%) i/s -    287.229k in  20.019188s
     inst attributes     37.593k (±11.6%) i/s -    738.990k in  20.060324s

# Rails 5.2

Warming up --------------------------------------
          initialize     4.128k i/100ms
         instantiate    22.420k i/100ms
     init attributes     2.363k i/100ms
     inst attributes     3.574k i/100ms
Calculating -------------------------------------
          initialize     39.157k (±24.7%) i/s -    718.272k in  20.034421s
         instantiate    255.087k (± 3.9%) i/s -      5.112M in  20.071522s
     init attributes     26.494k (± 7.2%) i/s -    526.949k in  20.017769s
     inst attributes     38.817k (± 6.7%) i/s -    775.558k in  20.079452s

JRuby 9.2.5

#  Rails 4.2

Warming up --------------------------------------
          initialize     1.330k i/100ms
         instantiate     5.152k i/100ms
     init attributes     1.770k i/100ms
     inst attributes     5.211k i/100ms
Calculating -------------------------------------
          initialize     21.175k (± 4.6%) i/s -    422.940k in  20.022394s
         instantiate     55.949k (± 8.7%) i/s -      1.108M in  20.022917s
     init attributes     18.940k (±14.4%) i/s -    368.160k in  20.042572s
     inst attributes     54.155k (± 8.6%) i/s -      1.073M in  20.008969s

# Rails 5.2

Warming up --------------------------------------
          initialize     5.263k i/100ms
         instantiate    39.091k i/100ms
     init attributes     3.660k i/100ms
     inst attributes     6.554k i/100ms
Calculating -------------------------------------
          initialize     62.631k (± 3.0%) i/s -      1.252M in  20.019361s
         instantiate    588.444k (± 3.3%) i/s -     11.766M in  20.020977s
     init attributes     39.746k (± 7.1%) i/s -    790.560k in  20.013695s
     inst attributes     67.973k (±11.4%) i/s -      1.337M in  20.032306s

// @brianstien @abrandoned @film42 @brettmortensen @newellista @Ffoeg311

abrandoned commented 5 years ago

where is the benchmark script you are running?

(btw looks amazing, just want to see how it's tested)

liveh2o commented 5 years ago

I went ahead and added it to master (https://github.com/liveh2o/active_remote/commit/94d07018227f8d67dc11b17ae3d926571f78afee) since we needed to compare this branch with the previous implementation. It's largely based on the script you made for https://github.com/ruby-protobuf/protobuf/pull/391.

liveh2o commented 5 years ago

Since this is a breaking change, I plan to merge this, along with some other changes, and get an alpha release out to test.

brianstien commented 5 years ago

@liveh2o What are we doing with UnknownAttributeError? Is that going to change with this release or later?

Also, can you update CHANGES.md?

liveh2o commented 5 years ago

@brianstien: that change didn't overlap with anything here, so I planned to do a follow up release. I also plan to update CHANGES once we release this.

liveh2o commented 5 years ago

Ended up creating an intermediate release that is compatible with Rails 5.0/5.1 that brought much of the speed gains posted here without the Rails 5.2 requirement (#71). The gains between this and that one are not as noticeable, but that's to be expected. I also opted to not to use the lazy attributes hash here, preserving the pattern of building from RPC from #71 because accessing the attributes after building from RPC is ~30% faster with it. I'll open a followup PR so we can discuss the differences.

Ruby 2.5.3

Warming up --------------------------------------
          initialize     4.158k i/100ms
         instantiate     9.918k i/100ms
     init attributes     2.443k i/100ms
     inst attributes     3.814k i/100ms
Calculating -------------------------------------
          initialize     41.927k (± 8.5%) i/s -    831.600k in  20.029387s
         instantiate    109.106k (± 4.2%) i/s -      2.182M in  20.041544s
     init attributes     27.180k (± 5.5%) i/s -    542.346k in  20.041329s
     inst attributes     47.298k (± 7.0%) i/s -    942.058k in  20.042198s

JRuby 9.2.5

Warming up --------------------------------------
          initialize     4.874k i/100ms
         instantiate    18.609k i/100ms
     init attributes     3.316k i/100ms
     inst attributes     7.227k i/100ms
Calculating -------------------------------------
          initialize     52.448k (± 6.7%) i/s -      1.043M in  20.002134s
         instantiate    217.332k (± 6.2%) i/s -      4.336M in  20.045337s
     init attributes     36.620k (± 6.4%) i/s -    729.520k in  20.018406s
     inst attributes     79.302k (± 6.1%) i/s -      1.583M in  20.044334s
liveh2o commented 5 years ago

Rebased from master, and re-ran the benchmarks:

Ruby 2.6.3 – Rails 5.1 (master)

Warming up --------------------------------------
          initialize     2.362k i/100ms
         instantiate     9.089k i/100ms
     init attributes     2.505k i/100ms
     inst attributes     8.457k i/100ms
Calculating -------------------------------------
          initialize     24.657k (±14.3%) i/s -    481.848k in  20.081592s
         instantiate     78.102k (±20.7%) i/s -      1.472M in  20.006263s
     init attributes     25.291k (± 7.3%) i/s -    503.505k in  20.039671s
     inst attributes     88.850k (± 4.0%) i/s -      1.776M in  20.023864s

Ruby 2.6.3 – Rails 5.2

Warming up --------------------------------------
          initialize     5.895k i/100ms
         instantiate     9.826k i/100ms
     init attributes     3.376k i/100ms
     inst attributes     4.888k i/100ms
Calculating -------------------------------------
          initialize     61.736k (± 2.8%) i/s -      1.238M in  20.068089s
         instantiate    103.805k (± 2.3%) i/s -      2.083M in  20.079060s
     init attributes     30.927k (±10.3%) i/s -    611.056k in  20.002828s
     inst attributes     51.121k (± 2.5%) i/s -      1.026M in  20.092732s

This should be ready to roll, @newellista!

newellista commented 5 years ago

:shipit:

abrandoned commented 5 years ago

@liveh2o are we at all worried about inst attributes being slower?

liveh2o commented 5 years ago

@abrandoned: I don't think so since we're simply using ActiveModel's internals. I think we have more performance gains that can be made once this is out.