Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
そんなリザルトキャッシュ 
で大丈夫か? 
@making 槙 俊明 
2014-09-17
ここでいうリザルトキャッシュ 
とは 
•重い処理の結果を格納するメモ 
リ(キャッシュ) 
•リザルトキャッシュを再利用す 
ることで性能向上が期待できる
あなたのリザルトキャッシュ 
•スレッドセーフですか? 
•スケーラブルですか?
5-6 「効率的でスケーラブ 
ルなリザルトキャッシュを 
構築する」 
の内容をご紹介します
たまにみる実装
たまにみる実装 
static Map<BigInteger, List<BigInteger>> cache 
= new HashMap<>; 
void doGet(…) { 
BigInteger n = …; 
List<BigInt...
たまにみる実装 
static Map<BigInteger, List<BigInteger>> cache 
= new HashMap<>; 
void doGet(…) { 
BigInteger n = …; 
List<BigInt...
たまにみる実装 
static Map<BigInteger, List<BigInteger>> cache 
= new HashMap<>; 
void doGet(…) { 
BigInteger n = …; 
List<BigInt...

static Map<BigInteger, List<BigInteger>> cache 
= new HashMap<>; 
void doGet(…) { 
BigInteger n = …; 
List<BigInteger> res...
よく見る実装 
static Map<BigInteger, List<BigInteger>> cache 
= new ConcurrentHashMap<>; 
void doGet(…) { 
BigInteger n = …; 
Li...
よく見る実装 
static Map<BigInteger, List<BigInteger>> cache 
= new ConcurrentHashMap<>; 
void doGet(…) { 
BigInteger n = …; 
Li...
Demo

check 
get calc put 
check 
get calc put
check 
get calc put 
check 
get calc put
check 
get calc put 
check 
get calc put 
まだputされていない
static Map<BigInteger, List<BigInteger>> cache 
= new ConcurrentHashMap<>; 
void doGet(…) { 
BigInteger n = …; 
List<BigIn...
FutureTaskを使って遅延評価
FutureTaskを使って遅延評価 
static Map<BigInteger, FutureTask<List<BigInteger>>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) ...
FutureTaskを使って遅延評価 
static Map<BigInteger, FutureTask<List<BigInteger>>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) ...
FutureTaskを使って遅延評価 
static Map<BigInteger, FutureTask<List<BigInteger>>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) ...
check 
get put calc 
check 
get put
Demo

check 
get put calc 
check 
get put 
calc
check 
get put calc 
check 
get put 
calc
check 
get put calc 
check 
get put 
calc 
新しいFutureTaskで上書きされた
check 
get put calc 
check 
get put 
calc 
結局2回計算 
新しいFutureTaskで上書きされた
FutureTaskを使って遅延評価 
static Map<BigInteger, FutureTask<List<BigInteger>>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) ...
ConcurrentMap#putIfAbsent
ConcurrentMap#putIfAbsent 
static ConcurrentMap<BigInteger, 
FutureTask<List<BigInteger>>> 
cache = new ConcurrentHashMap<...
ConcurrentMap#putIfAbsent 
static ConcurrentMap<BigInteger, 
FutureTask<List<BigInteger>>> 
cache = new ConcurrentHashMap<...
check 
get pIA calc 
check 
get pIA 
pIA … putIfAbsent
check 
get pIA calc 
check 
get pIA 
pIA … putIfAbsent 
put済みなので上書きしない
Demo

でも面倒くさいね! 

Java SE 8から
Java SE 8から 
static ConcurrentHashMap<BigInteger, List<BigInteger>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) { 
Bi...
Java SE 8から 
static ConcurrentHashMap<BigInteger, List<BigInteger>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) { 
Bi...
Java SE 8から 
static ConcurrentHashMap<BigInteger, List<BigInteger>> 
cache = new ConcurrentHashMap<>; 
void doGet(…) { 
Bi...
Demo
Cool! 

まとめ 
•ConcurrentHashMap#putIfAbsent + 
FutureTaskで効率的なリザルトキャッシュ 
を実装できる  
•JDK8からは 
ConcurrentHashMap#computeIfAbsent 
でお...
Java SE 8を使おう
ご清聴 
ありがとうございました
そんなリザルトキャッシュで大丈夫か? #jjug
Upcoming SlideShare
Loading in …5
×

そんなリザルトキャッシュで大丈夫か? #jjug

JJUGナイトセミナー2014年9月のセッション 「そんなリザルトキャッシュで大丈夫か?」 のスライドです。

Related Books

Free with a 30 day trial from Scribd

See all
  • Be the first to comment

そんなリザルトキャッシュで大丈夫か? #jjug

  1. 1. そんなリザルトキャッシュ で大丈夫か? @making 槙 俊明 2014-09-17
  2. 2. ここでいうリザルトキャッシュ とは •重い処理の結果を格納するメモ リ(キャッシュ) •リザルトキャッシュを再利用す ることで性能向上が期待できる
  3. 3. あなたのリザルトキャッシュ •スレッドセーフですか? •スケーラブルですか?
  4. 4. 5-6 「効率的でスケーラブ ルなリザルトキャッシュを 構築する」 の内容をご紹介します
  5. 5. たまにみる実装
  6. 6. たまにみる実装 static Map<BigInteger, List<BigInteger>> cache = new HashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { result = PrimeFactor.divide(n); // 素因数分解 cache.put(n, result); } // … }
  7. 7. たまにみる実装 static Map<BigInteger, List<BigInteger>> cache = new HashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { result = PrimeFactor.divide(n); // 素因数分解 cache.put(n, result); } // … }
  8. 8. たまにみる実装 static Map<BigInteger, List<BigInteger>> cache = new HashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { result = PrimeFactor.divide(n); // 素因数分解 cache.put(n, result); } // … } キャッシュになかったら 計算してキャッシュに追加
  9. 9.
  10. 10. static Map<BigInteger, List<BigInteger>> cache = new HashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { result = PrimeFactor.divide(n); // 素因数分解 cache.put(n, result); } // … } スレッドアンセーフ
  11. 11. よく見る実装 static Map<BigInteger, List<BigInteger>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { result = PrimeFactor.divide(n); // 素因数分解(重い処理) cache.put(n, result); } // … }
  12. 12. よく見る実装 static Map<BigInteger, List<BigInteger>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { スレッドセーフなMapに変更 result = PrimeFactor.divide(n); // 素因数分解(重い処理) cache.put(n, result); } // … }
  13. 13. Demo
  14. 14.
  15. 15. check get calc put check get calc put
  16. 16. check get calc put check get calc put
  17. 17. check get calc put check get calc put まだputされていない
  18. 18. static Map<BigInteger, List<BigInteger>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.get(n); if (result == null) { result = PrimeFactor.divide(n); // 素因数分解(重い処理) cache.put(n, result); } // … } Atomicじゃない
  19. 19. FutureTaskを使って遅延評価
  20. 20. FutureTaskを使って遅延評価 static Map<BigInteger, FutureTask<List<BigInteger>>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; FutureTask<List<BigInteger>> result = cache.get(n); if (result == null) { result = new FutureTask<>(() -> PrimeFactor.divide(n))); cache.put(n, result); result.run(); } // (略) result.get()で結果取得できるまでブロックする }
  21. 21. FutureTaskを使って遅延評価 static Map<BigInteger, FutureTask<List<BigInteger>>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; FutureTask<List<BigInteger>> result = cache.get(n); if (result == null) { result = new FutureTask<>(() -> PrimeFactor.divide(n))); cache.put(n, result); result.run(); Callableで処理を記述 } // (略) result.get()で結果取得できるまでブロックする }
  22. 22. FutureTaskを使って遅延評価 static Map<BigInteger, FutureTask<List<BigInteger>>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; FutureTask<List<BigInteger>> result = cache.get(n); if (result == null) { result = new FutureTask<>(() -> PrimeFactor.divide(n))); cache.put(n, result); result.run(); Callableで処理を記述 } // (略) result.get()で結果取得できるまでブロックする } キャッシュに入れてから処理実行
  23. 23. check get put calc check get put
  24. 24. Demo
  25. 25.
  26. 26. check get put calc check get put calc
  27. 27. check get put calc check get put calc
  28. 28. check get put calc check get put calc 新しいFutureTaskで上書きされた
  29. 29. check get put calc check get put calc 結局2回計算 新しいFutureTaskで上書きされた
  30. 30. FutureTaskを使って遅延評価 static Map<BigInteger, FutureTask<List<BigInteger>>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; FutureTask<List<BigInteger>> result = cache.get(n); if (result == null) { result = new FutureTask<>(() -> PrimeFactor.divide(n))); cache.put(n, result); result.run(); } // (略) result.get()で結果取得できるまでブロックする } Atomicじゃない
  31. 31. ConcurrentMap#putIfAbsent
  32. 32. ConcurrentMap#putIfAbsent static ConcurrentMap<BigInteger, FutureTask<List<BigInteger>>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; FutureTask<List<BigInteger>> result = cache.get(n); if (result == null) { FutureTask<List<BigInteger>> ft = new FutureTask<>(() -> PrimeFactor.divide(n))); result = cache.putIfAbsent(n, result); if (result == null) {ft.run(); result = ft;} } // (略) result.get()で結果取得できるまでブロックする
  33. 33. ConcurrentMap#putIfAbsent static ConcurrentMap<BigInteger, FutureTask<List<BigInteger>>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; FutureTask<List<BigInteger>> result = cache.get(n); if (result == null) { FutureTask<List<BigInteger>> ft = new FutureTask<>(() -> PrimeFactor.divide(n))); result = cache.putIfAbsent(n, result); if (result == null) {ft.run(); result = ft;} } // (略) result.get()で結果取得できるまでブロックする キーが存在しない場合はnullを、 存在する場合はそれを返す
  34. 34. check get pIA calc check get pIA pIA … putIfAbsent
  35. 35. check get pIA calc check get pIA pIA … putIfAbsent put済みなので上書きしない
  36. 36. Demo
  37. 37.
  38. 38. でも面倒くさいね! 
  39. 39. Java SE 8から
  40. 40. Java SE 8から static ConcurrentHashMap<BigInteger, List<BigInteger>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.computeIfAbsent(n, (x) -> PrimeFactor.divide(x)); // … }
  41. 41. Java SE 8から static ConcurrentHashMap<BigInteger, List<BigInteger>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.computeIfAbsent(n, (x) -> PrimeFactor.divide(x)); // … } キーが存在しない場合はラムダ式 の計算結果を返す
  42. 42. Java SE 8から static ConcurrentHashMap<BigInteger, List<BigInteger>> cache = new ConcurrentHashMap<>; void doGet(…) { BigInteger n = …; List<BigInteger> result = cache.computeIfAbsent(n, PrimeFactor::divide); // … } メソッド参照でOK
  43. 43. Demo
  44. 44. Cool! 
  45. 45. まとめ •ConcurrentHashMap#putIfAbsent + FutureTaskで効率的なリザルトキャッシュ を実装できる  •JDK8からは ConcurrentHashMap#computeIfAbsent でおk 
  46. 46. Java SE 8を使おう
  47. 47. ご清聴 ありがとうございました

    Be the first to comment

    Login to see the comments

  • takecy

    Sep. 17, 2014
  • KanSakamoto

    Sep. 17, 2014
  • KeisukeTkeuchi

    Sep. 17, 2014
  • akisei

    Sep. 17, 2014
  • hashimotoms

    Sep. 17, 2014
  • fukuihi

    Sep. 17, 2014
  • AijazAhmed10

    Sep. 18, 2014
  • ohtsuchi

    Sep. 18, 2014
  • takehiroinoue127

    Sep. 18, 2014
  • YoshioHara

    Sep. 18, 2014
  • matsumana0101

    Sep. 18, 2014
  • hiro_ist

    Sep. 19, 2014
  • mitsuruogawa33

    Sep. 20, 2014
  • TakashiYasukawa1

    Sep. 23, 2014
  • itokami1123

    Sep. 28, 2014
  • masakazuyamanaka

    Sep. 29, 2014
  • orekyuu

    Oct. 5, 2014
  • TsukasaTamaru

    Nov. 22, 2014
  • sfus

    Sep. 17, 2015
  • kbhrs

    Oct. 7, 2015

JJUGナイトセミナー2014年9月のセッション 「そんなリザルトキャッシュで大丈夫か?」 のスライドです。

Views

Total views

10,344

On Slideshare

0

From embeds

0

Number of embeds

2,198

Actions

Downloads

26

Shares

0

Comments

0

Likes

36

×