Upgrade to Pro — share decks privately, control downloads, hide ads and more …

realtime-ranking.pdf

miio
March 20, 2013

 realtime-ranking.pdf

Ruby勉強会 札幌24で発表しました

miio

March 20, 2013
Tweet

More Decks by miio

Other Decks in Technology

Transcript

  1. ࣗݾ঺հ Έ͓͌ (miio) Kawaz ( http://www.kawaz.org ) LOCAL ( http://www.local.or.jp

    ) Twitter ( @ayako119 ) ࡳຈͰιʔγϟϧήʔϜ࡞ͬͯ·͢ 2
  2. 5

  3. ۩ମతͳ΍Γํ id user_id score partition id 1 1 600 1

    2 2 800 1 3 3 1020 2 id min max user count 1 0 999 2 2 1000 1999 1 UserHighScore HighScorePartition ύʔςΟγϣϯͰ۠੾Δͱ͍͏ߟ͑ํ 17
  4. ͪΐͬͱ໰୊఺ ৽͍͠είΞͷύʔςΟγϣϯΛٻΊΔࡍͷ৚͕݅ࣜԼهͩͬͨ min <= ◦◦ AND ◦◦ <= max ͜Εͩͱɺ૝ఆ͍ͯ͠ͳ͍ߦʹ΋ϩοΫ͕͔͔ΔՄೳੑ͕͋Δ͜ͱ

    ͕෼͔ͬͨ(EXPLAINͯ͠ΈͨΒεΩϟϯର৅͕޿ൣғͩͬͨ) ͪͳΈʹΠϯσοΫε͸ min, maxͷෳ߹ΠϯσοΫεͰͨ͠ ϩοΫൣғ͸ڱ͍΄͏͕͍͍ʂ 18
  5. class HighScorePartitionMap PARTITIONS = { 0 => {id: 1, max:

    7999}, 8000 => {id: 2, max: 15999}, 16000 => {id: 3, max: 23999}, 24000 => {id: 4, max: 31999}, 32000 => {id: 5, max: 39999}, 40000 => {id: 6, max: 47999}, 48000 => {id: 7, max: 55999}, 56000 => {id: 8, max: 63999}, ~~தུ~~ 740000 => {id: 126, max: 747999}, 748000 => {id: 127, max: 755999}, 756000 => {id: 128, max: 763999} } end ࠷খ஋ΛΩʔͱͯ͠ɺidͱmaxͷϖΞΛ࣋ͨͤ·ͨ͠ 21
  6. before_save do |r| partition_map = HighScorePartitionMap::PARTITIONS.select {|k,v| k <= r.score

    and v[:max] >= r.score}.values.first # Not modify return true if r.high_score_partition_id == partition_map[:id] if r.high_score_partition_id partition_where = [r.high_score_partition_id, partition_map[:id]] else partition_where = partition_map[:id] end partition = HighScorePartition.where(id: partition_where).lock(true).all.select{|v| v.id == partition_map[:id]}.first # Not found partition if cheat? raise "Score not found range partition" unless partition # Remove user for old pertition HighScorePartition.decrement_counter(:user_count, r.high_score_partition_id) if r.high_score_partition_id # Add user for new partition HighScorePartition.increment_counter(:user_count, partition) # New partition self.high_score_partition = partition end 24
  7. def rank_range user_count = 0 users = self.class.upper_byrange(self.score).limit(10).all return users

    if users.length >= 10 user_count = users.count if users.count if self.current_rank >= 10 partitions = HighScorePartition.order('min DESC').all else partitions = HighScorePartition.upper(self.score).order('min DESC').all end partitions.each do |partition| users << partition.user_high_scores.limit(10).all user_count += partition.user_count return users if user_count >= 10 end end 27
  8. ϕϯνϚʔΫ user system total real 1time legacy: 0.140000 0.010000 0.150000

    ( 0.295606) 1time new: 0.040000 0.010000 0.050000 ( 0.081668) 100time legacy: 0.480000 0.180000 0.660000 ( 1.161972) 100time new: 1.010000 0.330000 1.340000 ( 1.306994) 250time legacy: 1.140000 0.290000 1.430000 ( 3.732233) 250time new: 2.540000 0.710000 3.250000 ( 3.080671) 1000time legacy: 6.740000 1.210000 7.950000 ( 24.415076) 1000time new: 12.830000 3.220000 16.050000 ( 15.357371) ※ new͕ύʔςΟγϣϯํࣜͰ͢ 34