ããã¯ãäœè
ã®åæãåŸãŠçºè¡ãããAlexey Shipilevã«ããèšäºãDo It YourselfïŒOpenJDKïŒGarbage Collectorãã®ç¿»èš³ã§ãã ã¿ã€ããã¹ããã®ä»ã®ãã°ãPMã«å ±åããŠãã ãã-ä¿®æ£ããŸãã
ã©ã³ã¿ã€ã ã§äœããäœæããããã»ã¹ã¯æ¥œããç·Žç¿ã§ãã å°ãªããšãæåã®ããŒãžã§ã³ã®äœæïŒ åäœã䟿å©ã«ç£èŠããã³ãããã°ã§ãããä¿¡é Œæ§ãé«ãã髿§èœã§ãã§ã€ã«ã»ãŒããªã©ã³ã¿ã€ã ãµãã·ã¹ãã ãæ§ç¯ããããšã¯ãéåžžã«å°é£ãªäœæ¥ã§ãã
åçŽãªã¬ããŒãžã³ã¬ã¯ã¿ãŒãäœæããã®ã¯äžèŠåçŽã§ãããã®èšäºã§ã¯ããããå®è¡ããããšèããŠããŸãã FOSDEM 2019ã®Roman Kennkeã¯ããã®ãããã®ä»¥åã®ããŒãžã§ã³ã䜿çšããŠã ã20åéã§GCãäœæããããšããã¿ã€ãã«ã®è¬æŒãšãã¢ãè¡ããŸããã ããã«å®è£
ãããã³ãŒãã¯å€ãã®ããšãå®èšŒããååã«ã³ã¡ã³ããããŠãããšããäºå®ã«ãããããããäœãèµ·ãã£ãŠããã®ãã«ã€ããŠã®é«ã¬ãã«ã®èª¬æãå¿
èŠã§ã-ããããã®èšäºã®ç»å Žã§ãã
ã¬ããŒãžã³ã¬ã¯ã¿ãŒã®äœæ¥ã®åºæ¬çãªçè§£ã¯ãããã«èšèŒãããŠããå
容ãçè§£ããã®ã«éåžžã«åœ¹ç«ã¡ãŸãã ãã®èšäºã§ã¯ãHotSpotã®ç¹å®ã®å®è£
ã§ä»æ§ãšã¢ã€ãã¢ã䜿çšããŸãããããã§ã¯GCèšèšã«é¢ããå
¥éã³ãŒã¹ã¯ãããŸããã GCãã³ãããã¯ãèªãã§ãGCã®åºæ¬ã«é¢ããæåã®ç« ãèªãã§ãã ãã ãããã«éããªããšããŠã£ãããã£ã¢ã®èšäºãå§ãŸããŸã ã

å
容
1. GCã®æ§æ
ããŸããŸãªGCãèšè¿°ãããã®ã§ãç¬èªã®GCãäœæããã®ã¯éåžžã«ç°¡åã§ãããã§ã«èšè¿°ãããŠããå€ãã®èŠçŽ ã䜿çšããŠãå®è£
ã®è©³çްã«é¢ããæžå¿µã®äžéšãå®èšŒæžã¿ã®ãã¹ãæžã¿ã®ã³ãŒãã«ç§»è¡ã§ããŸã
1.1ã ã€ãã·ãã³GC
OpenJDK 11ã§ã¯ãæ°ããJEP 318ïŒ EpsilonïŒA No-Op Garbage CollectorïŒExperimentalïŒãå°å
¥ãããŸããã ãã®ã¿ã¹ã¯ã¯ãã¡ã¢ãªã®è§£æŸãäžèŠãªå ŽåãçŠæ¢ãããŠããå Žåã§ããæå°éã®å®è£
ãæäŸããããšã§ãã JEPã§ã¯ããªãæçšãªã®ãã«ã€ããŠè©³ãã説æããŸãã
å®è£
ã®èгç¹ããããã¬ããŒãžã³ã¬ã¯ã¿ãŒãã¯æªãååã§ããã¡ã¢ãªã®å²ãåœãŠãšè§£æŸã®äž¡æ¹ãæ
åœãããèªåã¡ã¢ãªãããŒãžã£ãŒããšããçšèªã䜿çšããæ¹ãæ£ããã§ãããã Epsilon GCã¯ãå²ãåœãŠãã®ã¿ãå®è£
ããããªãªãŒã¹ãã¯äžååŠçããŸããã ãããã£ãŠãEpsilon GCã䜿çšããŠãããªãªãŒã¹ãã¢ã«ãŽãªãºã ã®å®è£
ããŒãããéå§ã§ããŸãã
1.1.1ã ã¡ã¢ãªå²ãåœãŠ
Epsilon GCã®æãéçºãããéšåã¯ã ã¡ã¢ãªã®å²ãåœãŠãæ
åœããŸã ã ä»»æã®ãµã€ãºã®ã¡ã¢ãªãå²ãåœãŠãå¿
èŠãªãµã€ãºã®ã¹ã¬ããããŒã«ã«å²ãåœãŠãããã¡ïŒTLABïŒãäœæããããã®å€éšãªã¯ãšã¹ããåŠçããŸãã å®è£
èªäœã¯ã空ãã¡ã¢ãªããªãã誰ã倱ããããã€ããè¿ããªããããTLABãéåºŠã«æ¡åŒµããªãããã«ããŠããŸãã
1.1.2ã éå£
ã¬ããŒãžã³ã¬ã¯ã¿ãŒã®äžã«ã¯ãGCäžå€æ¡ä»¶ãç¶æããããã«ã¢ããªã±ãŒã·ã§ã³ãšã®å¯Ÿè©±ãå¿
èŠãšãããã®ããããããŒãã«ã¢ã¯ã»ã¹ããããšãããšã©ã³ã¿ã€ã ãšã¢ããªã±ãŒã·ã§ã³ãããããããªã¢ãäœæããããã«åŒ·å¶ããŸãã ããã¯ããã¹ãŠã®ãã«ãã¹ã¬ããã³ã¬ã¯ã¿ãŒã ãã§ãªããäžä»£ãæã¡äžçãæ¢ããŠããå€ãã®ã³ã¬ã¯ã¿ãŒã«ãåœãŠã¯ãŸããŸãã
Epsilonã¯ããªã¢ãå¿
èŠãšããŸããããã©ã³ã¿ã€ã ãšã³ã³ãã€ã©ãŒã¯ããªã¢ãäœãããªãããšããŸã ç¥ãããã§ãã ãã€ã§ãã©ãã§ããããåŠçããã®ã¯é¢åã§ãã 幞ããªããšã«ãOpenJDK 11以éãæ°ããJEP-304ããããŸãããGarbage Collection Interfaceãã§ã ãããã«ãããããªã¢ã®æ¿å
¥ãã¯ããã«ç°¡åã«ãªããŸãã ç¹ã«ã Epsilonã§èšå®ãããããªã¢ã¯ç©ºã§ãããä¿åãèªã¿èŸŒã¿ãCASãarraycopyãªã©ã®ç°¡åãªäœæ¥ã¯ãã¹ãŠãæ¢åã®ã¹ãŒããŒã¯ã©ã¹ããç°¡åãªããªã¢ã®å®è£
ã«å§ä»»ã§ããŸãã ããªã¢ãå¿
èŠãšããªãGCãäœæããŠããå Žåã¯ãEpsilonã®ã³ãŒããç°¡åã«åå©çšã§ããŸãã
1.1.3ã æ¥ç¶ã®ç£èŠ
GCå®è£
ã®ââæåŸã®éå±ãªéšåã¯ãJVMå
ã®äžé£ã®ç£èŠã¡ã«ããºã ãžã®ããã¯ã§ããMXãã³ã蚺æã³ãã³ããªã©ãæ©èœããã¯ãã§ãã ã€ãã·ãã³ã¯ãã§ã«ããããã¹ãŠè¡ã£ãŠããŸãã
1.2ã ã©ã³ã¿ã€ã ãšGC
1.2.1ã ã«ãŒãèŠçŽ
äžè¬ã«ãã¬ããŒãžã³ã¬ã¯ã¿ã¯ãJavaã©ã³ã¿ã€ã ã®ããŒãåç
§ãæ£ç¢ºã«ç¥ãå¿
èŠããããŸãã GCã«ãŒããšåŒã°ãããããã®ã«ãŒãèŠçŽ ã¯ãã¹ããªãŒã ã¹ã¿ãã¯ãšããŒã«ã«å€æ°ïŒJITã³ã³ãã€ã«ã³ãŒãã«ãããã®ãå«ãïŒïŒããã€ãã£ãã¯ã©ã¹ãšã¯ã©ã¹ããŒããŒãJNIã®åç
§ãªã©ã®ã¹ãããã«ãªããŸãã ãããã®èŠçŽ ãç¹å®ãã詊ã¿ã¯ãéåžžã«è€éã§éå±ã§ãã ãããããããã¹ãããã§ã¯ããããã¯ãã¹ãŠé©åãªVMãµãã·ã¹ãã ã䜿çšããŠè¿œè·¡ããããããæ¢åã®GCå®è£
ãããããšã©ã®ããã«æ©èœããããç°¡åã«ç¥ãããšãã§ããŸãã ããã«æ¬æã§ãããèŠãã§ãããã
1.2.2ã ãªããžã§ã¯ãã®ã¯ããŒã«
ã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ãJavaãªããžã§ã¯ãã®ã¢ãŠãããŠã³ããªã³ã¯ããã€ãã¹ããå¿
èŠããããŸãã ãã®æäœã¯ã©ãã«ã§ãããã®ã§ãã©ã³ã¿ã€ã ã®å
±ééšåã¯æ¢æã®åé¿çãæäŸããŸã;èªåã§äœããæžãå¿
èŠã¯ãããŸããã 以äžã«ç¹å®ã®å®è£
ãå«ãã»ã¯ã·ã§ã³ããããŸããããšãã°ãåŒã³åºãobjâoop_iterate
èŠã€ããããšãã§ããŸãã
1.2.3ã å€äœ
ç§»åããã¬ããŒãžã³ã¬ã¯ã¿ã¯ãç§»åãããªããžã§ã¯ãã®æ°ããã¢ãã¬ã¹ãã©ããã«æžãçããå¿
èŠããããŸãã ãã®è»¢éããŒã¿ãæžã蟌ãããšãã§ããå Žæã¯ããã€ããããŸãã
- ãªããžã§ã¯ãèªäœ ïŒã·ãªã¢ã«ããã©ã¬ã«ãªã©ïŒã§ãããŒã«ãŒã¯ãŒãããåå©çšã§ããŸã ã ã¯ãŒã«ãã忢ãããšããªããžã§ã¯ããžã®ãã¹ãŠã®ã¢ã¯ã»ã¹ãå¶åŸ¡ãããããŒã«ãŒã¯ãŒãã«å
¥åããããšã«ããäžæããŒã¿ãJavaã¹ã¬ããã衚瀺ã§ããªãããšãä¿èšŒãããŸãã 転éããŒã¿ãä¿åããããã«åå©çšã§ããŸãã
- å¥ã®ãã€ãã£ãç§»åããŒãã«ïŒ ZGC ãC4ãªã©ïŒãç¶æã§ããŸãã ããã«ãããGCã¯ã©ã³ã¿ã€ã ãšã¢ããªã±ãŒã·ã§ã³ã®æ®ãã®éšåããå®å
šã«åé¢ãããŸããããã¯ãGCã ãããã®ãããªããŒãã«ã®ååšãç¥ã£ãŠããããã§ãã ç«¶äºåã®ããã¢ã»ã³ãã©ãŒã¯éåžžããã®ãããªã¹ããŒã ã䜿çšããŸã-圌ãã¯äžå¿
èŠãªåé¡ã®æã§èŠããããšãæã¿ãŸããã
- ãªããžã§ã¯ãã«å¥ã®åèªã远å ã§ããŸãïŒ ã·ã§ãã³ãã¢ãªã©ïŒã åè¿°ã®2ã€ã®ã¢ãããŒãã®ãã®çµã¿åããã«ãããã©ã³ã¿ã€ã ãšã¢ããªã±ãŒã·ã§ã³ãæ¢åã®ããããŒãåé¡ãªã䜿çšã§ããããã«ãªãã ãã§ãªãã転éããŒã¿ãç¯çŽãããŸãã
1.2.4ã ããŒã«ãŒããŒã¿
ã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ã ããŒãã³ã°ããŒã¿ãã©ããã«æžã蟌ãå¿
èŠããããŸãã ç¹°ãè¿ããŸãããããããä¿åããã«ã¯ããã€ãã®æ¹æ³ããããŸãã
- ãªããžã§ã¯ãèªäœïŒã·ãªã¢ã«ããã©ã¬ã«ãªã©ïŒã§ããŒã«ãŒã¯ãŒããåå©çšã§ããŸãã ç¹°ãè¿ããŸãããã¯ãŒã«ãã¹ãããã¢ãŒãã§ã¯ãããŒã«ãŒã¯ãŒãã®ãããã䜿çšããŠãã¿ã°ã®ãã¡ã¯ãããšã³ã³ãŒãã§ããŸãã ããã«ããã¹ãŠã®çããŠãããªããžã§ã¯ããç§»åããå¿
èŠãããå Žåã¯ãããŒãã«æ²¿ã£ãŠãªããžã§ã¯ãããšã«ç§»åããŸããããã¯ã ããŒããè§£æå¯èœã§ããããã«å¯èœã§ãã
- ããŒãã³ã°ããŒã¿ïŒG1ãShenandoahãªã©ïŒãä¿åããããã®å¥ã®æ§é ãç¶æã§ããŸãã ããã¯éåžžãããŒãã®Nãã€ãããšã«ã«ãŒãã®1ãããã«ãããããåå¥ã®ããããããã䜿çšããŠè¡ãããŸãã éåžžãJavaãªããžã§ã¯ãã¯8ãã€ãã§æŽåããããããã«ãŒãã¯ããŒããã64ãããããšã«ã«ãŒãã®1ãããã«ããããããã€ãã£ãã¡ã¢ãªã®ããŒããµã€ãºã®1/64ãå æããŸãã ãããã®ãªãŒããŒãããã¯ãããŒããã¹ãã£ã³ããŠçããŠãããªããžã§ã¯ããç¹ã«ã¹ããŒã¹ãªããžã§ã¯ãã®ååšã確èªããå Žåã«å¹æããããŸãããããããã€ãã¹ããããšã¯ããªããžã§ã¯ãããšã«ãœãŒããããããŒãããã€ãã¹ãããããã¯ããã«é«éã§ãã
- ã©ãã«ããªã³ã¯èªäœã«ãšã³ã³ãŒãããŸãïŒZGCãC4ãªã©ïŒã ããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãšã®èª¿æŽãå¿
èŠã§ãããªã³ã¯ãããããã®ã©ãã«ããã¹ãŠåé€ããããæ£ç¢ºæ§ãç¶æããããã«ä»ã®ããã€ãã®ããªãã¯ãå®è¡ããå¿
èŠããããŸãã ã€ãŸããGCããã®éå£ãŸãã¯è¿œå ã®äœæ¥ãå¿
èŠã§ãã
2.äžè¬èšç»
æãå¯èœæ§ãé«ãã®ã¯ãEpsilonã®äžã«å®è£
ããã®ãæãç°¡åãªã®ã¯ãLISP2ã¹ã¿ã€ã«ã®Mark-Compactã§ãã ãã®GCã®åºæ¬çãªèãæ¹ã¯ãWikipediaãšGCãã³ããã㯠ïŒ3.2ç« ïŒã®äž¡æ¹ã§èª¬æãããŠããŸãã ã¢ã«ãŽãªãºã ã®ã¹ã±ããã¯ã以äžã®å®è£
ã«é¢ããã»ã¯ã·ã§ã³ã«ãããŸããããŠã£ãããã£ã¢ãŸãã¯GCãã³ãããã¯ãèªãã§ãäœãããããšããŠããã®ããçè§£ããããšã匷ããå§ãããŸãã
åé¡ã®ã¢ã«ãŽãªãºã ã¯ãGCã®ã·ããã§ããç§»åãããªããžã§ã¯ãã¯ãããŒãå
ã®å
é ã«é
åã§ç§»åããŸãã é·æãšçæããããŸãã
- ã¡ã¢ãªå²ãåœãŠã®é åºãç¶æããŸãã ããã¯ãã¡ã¢ãªå
ã®ã¬ã€ã¢ãŠããå¶åŸ¡ããã®ã«éåžžã«é©ããŠããŸãïŒããªãã«ãšã£ãŠéèŠãªå Žåã¯ãã³ã³ãããŒã«ã®ããªãŒã¯ãããªãã®æéã§ãïŒïŒã æ¬ ç¹ã¯ããã®æ¹æ³ã§ã¯èªåãªã³ã¯ããŒã«ãªãã£ãåŸãããªãããšã§ãã
- ãã®è€éãã¯ããªããžã§ã¯ãæ°ã®OïŒNïŒã§ãã ãã ããçŽç·æ§ã«ã¯ä»£åã䌎ããŸããGCã¯ããã«ããµã€ã¯ã«ããšã«4åã®æããã€ãã¹ããå¿
èŠããããŸãã
- ããŒãäžã®ç©ºãã¡ã¢ãªã¯å¿
èŠãããŸããïŒ çããŠãããªããžã§ã¯ããéé¿ããããã«ããŒãäžã®ã¡ã¢ãªãäºçŽããå¿
èŠã¯ãããŸããããããã£ãŠã99ã§ãªãŒããŒãããŒããããŒãã§äœæ¥ããããšãã§ããŸããïŒ9ïŒïŒ
ã åçŽãªã³ã¬ã¯ã¿ãŒã®ä»ã®ã¢ã€ãã¢ãããšãã°ãã»ãã¹ããŒã¹ãæã€ã¹ã«ãã³ãžã£ãŒïŒã»ãã¹ããŒã¹ã¹ã«ãã³ãžã£ãŒïŒãåãäžããå ŽåãããŒãã®è¡šç€ºããããã«æžãçŽããŠãé¿é£çšã®ã¹ããŒã¹ãå°ã確ä¿ããå¿
èŠããããŸãããããã¯ãã®æŒç¿ã®ç¯å²å€ã§ãã
- åé¡ã«å°ãåãçµããšãGCãéã¢ã¯ãã£ããªæéäžã«ã¡ã¢ãªãšæéã®æ¶è²»ããŒãã«ããããšãã§ããŸãã ä»»æã®ç¶æ
ã®ã¡ã¢ãªã§éå§ãã忢ããŠã倧å¹
ã«å§çž®ããŸãã ããã¯ãEpsilonã®åäœã«éåžžã«ããé©åããŸããæåŸã®ãªããžã§ã¯ãã®çŽåŸã«åŒ·èª¿è¡šç€ºãç¶ããã ãã§ãã ããã¯ãã€ãã¹ã§ããããŸããããŒãã®å
é ã«ããããã€ãã®æ»ãã ãªããžã§ã¯ãã¯ã倿°ã®åãããããããŸãã
- æ°ããããªã¢ãå¿
èŠãšããªãã ãã§ã
EpsilonBarrierSet
ãã®ãŸãŸåå©çšã§ããŸãã
ç°¡åã«ããããã«ãGCã®å®è£
ã§ã¯äžçã®å®å
šãªåæ¢ïŒstop-the-worldãSTWïŒã䜿çšããäžä»£ããã«ãã¹ã¬ããããããŸããã ãã®å Žåãããããããã䜿çšããŠããŒã¯ãä¿åããããŒã«ãŒã¯ãŒããåå©çšããŠç§»åããŒã¿ãä¿åããã®ãçã«ããªã£ãŠããŸãã
3. GCã³ã¢ã®å®è£
å®è£
å
šäœãèªãã§çè§£ããããšã¯ãç¡ç¥ãªäººã«ãšã£ãŠã¯è€éããããããããŸããã ãã®ã»ã¯ã·ã§ã³ã§ã¯ãã¹ãããããšã«èª¬æããŸãã
3.1ã ããããŒã°
éåžžãã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ããã«ãã®æºåãšããŠããã€ãã®ããšãè¡ãå¿
èŠããããŸãã ã³ã¡ã³ããèªãã§ãã ããã圌ãã¯åœŒãèªèº«ã®ããã«è©±ãã¹ãã§ãïŒ
{ GCTraceTime(Info, gc) time("Step 0: Prologue", NULL);
ããããããã䜿çšããŠãªããžã§ã¯ãã®å°éå¯èœæ§ã远跡ããããã䜿çšããåã«ãããããããã¯ãªã¢ããå¿
èŠããããŸãã ãŸãã¯ãç§ãã¡ã®å ŽåãGCãµã€ã¯ã«ãéå§ããåã«ãªãœãŒã¹ãèŠæ±ããªãããšãç®æããŠãããããäºåã«ãããããããã¡ã¢ãªã«ã³ãããããå¿
èŠããããŸãã ããã«ãããå°ãªããšãLinuxã§ã¯ãç¹ã«ã¹ããŒã¹ããŒãã®å Žåãããããããã®ã»ãšãã©ãããŒãžãŒãããã€ã³ããããããããã€ãã®è峿·±ãå©ç¹ããããŸãã
ã¹ã¬ããã¯TLABãè§£æŸãããã«ãã®å®äºåŸã«GCã«æ°ãããã®ãèŠæ±ããå¿
èŠããããŸãã
TLABãšjava.lang.ThreadLocal
æ··åããªãã§ãã ããã GCã®èгç¹ããã¯ãThreadLocalã¯éåžžã®ãªããžã§ã¯ãã§ãããJavaã³ãŒãã§ç¹ã«å¿
èŠãšãããªãéããGCã«ãã£ãŠã³ã³ãã€ã«ãããŸããã
ã©ã³ã¿ã€ã ã®äžéšãç¹ã«JavaããŒããžã®ãªã³ã¯ãä¿æããŠããéšåã¯ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³äžã«ç ŽæãããããGCãããã«åäœãå§ããããšãç¹ã«èŠåããå¿
èŠããããŸãã ããã«ãããGCãç§»åããåã«ãåãµãã·ã¹ãã ãç¶æ
ã®äžéšãæºåããŠä¿åã§ããããã«ãªããŸãã
3.2ã ããŒãã³ã°
äžçã®ã¹ãããã¢ãŒãã§ã®ããŒãã³ã°ã¯ãã»ãšãã©ãã¹ãŠãæ¢ã«è¡ãããŠããå Žåãéåžžã«ç°¡åã«ãªããŸãã ã©ãã«ä»ãã¯éåžžã«æšæºçã§ãããå€ãã®å®è£
ã§ã¯ãGCãæåã®ã¹ãããã§ããå¯èœæ§ãé«ãã§ãã
{ GCTraceTime(Info, gc) time("Step 1: Mark", NULL);
ããã¯ãä»ã®ã°ã©ããšãŸã£ããåãããã«æ©èœããŸããæåã®å°éå¯èœãªé ç¹ã®ã»ããã§ãã©ããŒãµã«ãéå§ããåºåãšããžã«æ²¿ã£ãŠé²ã¿ã蚪åãããã¹ãŠã®é ç¹ãèšé²ããŸãã ãã¢ãŒã¯ãæªèšªåã®ããŒã¯ããã¹ãŠçµãããŸã§ç¶ããŸãã GCã§ã¯ããé ç¹ãã¯ãªããžã§ã¯ãã§ãããããšããžãã¯ãããã®éã®ãªã³ã¯ã§ãã
æè¡çã«ã¯ããªããžã§ã¯ãã®ã°ã©ããååž°çã«ãã©ãããšãã§ããŸãããããã¯éåžžã«å€§ããªçŽåŸãæã€ããšãã§ããä»»æã®ã°ã©ãã«ãšã£ãŠã¯æªãèãã§ãã 10åã®ããŒã¯ã®ãªã³ã¯ãªã¹ããæ³åããŠãã ããïŒ ãããã£ãŠãååž°ã®æ·±ããå¶éããããã«ãæ€åºããããªããžã§ã¯ããèšé²ããããŒãã³ã°ã¹ã¿ãã¯ã䜿çšããŸãã
å°éå¯èœãªãªããžã§ã¯ãã®åæã»ããã¯GCã«ãŒãã§ãã ããã§ã process_roots
ã«ã€ããŠè©³ããprocess_roots
ããŸããã詳现ã«ã€ããŠã¯åŸã§èª¬æããŸãã ä»ã®ãšãããVMåŽããã®ãã¹ãŠã®å°éå¯èœãªãªã³ã¯ããã€ãã¹ããŠãããšã ãèšã£ãŠãããŸãããã
ããŒã¯ä»ãã®ããããããã¯ã ããŒãã³ã°æ³¢é¢ ïŒæ¢ã«èšªããå€ãã®ãªããžã§ã¯ãïŒãèšé²ããããŒã«ãšããŠæ©èœããæçµçã«ã¯ãç®çã®çµæã®ãªããžããªãå°éå¯èœãªãã¹ãŠã®ãªããžã§ã¯ãã®ã»ãããšããŠæ©èœããŸãã å®éã®äœæ¥ã¯EpsilonScanOopClosure
ã§è¡ããããã¹ãŠã®è峿·±ããªããžã§ã¯ãã«é©çšãããéžæãããªããžã§ã¯ãã®ãã¹ãŠã®ãªã³ã¯ã§EpsilonScanOopClosure
ããŸãã
èŠãŠãã ãããJavaã¯ãã¡ãã·ã§ããã«ã«ãªãåã«éããããšãã§ããŸããïŒ
class EpsilonScanOopClosure : public BasicOopIterateClosure { private: EpsilonMarkStack* const _stack; MarkBitMap* const _bitmap; template <class T> void do_oop_work(T* p) {
ãã®æé ãå®äºãããšã _bitmap
ã«ã¯ã©ã€ããªããžã§ã¯ãã®å Žæã瀺ãããããå«ãŸããŸãã ããã«ããããã¹ãŠã®çããŠãããªããžã§ã¯ãããã€ãã¹ããããšãã§ããŸããäŸãã°ïŒ
3.3ã æ°ããäœæãèšç®ãã
ãããéåžžã«ç°¡åãªæé ã§ãããã¢ã«ãŽãªãºã ã®èª¬æã©ããã«å®è£
ãããŸãã

ç®ãåŒãå¯äžã®ããšã¯ãJavaãªããžã§ã¯ãã®ããŒãã³ã°ã¯ãŒãã«æ°ããã¢ãã¬ã¹ãæ ŒçŽããããšã決å®ããããšã§ãããã®ã¯ãŒãã¯ãããšãã°ããã¯ã«é¢ããæ
å ±ãªã©ãéèŠãªãã®ã§ãã§ã«å æãããŠããå¯èœæ§ããããŸãã 幞ããªããšã«ããã®ãããªéèŠãªåèªã¯éåžžã«ãŸãã§ãããå¿
èŠãªå Žåã¯åçŽã«åå¥ã«ä¿åã§ããŸãããããPreservedMarks
䜿çšç®çã§ãã
å®éã®ã¢ã«ãŽãªãºã ã®äœæ¥ã¯ã EpsilonCalcNewLocationObjectClosure
ã«ãã£ãŠè¡ããEpsilonCalcNewLocationObjectClosure
ã
class EpsilonCalcNewLocationObjectClosure : public ObjectClosure { private: HeapWord* _compact_point; PreservedMarks* const _preserved_marks; public: EpsilonCalcNewLocationObjectClosure(HeapWord* start, PreservedMarks* pm) : _compact_point(start), _preserved_marks(pm) {} void do_object(oop obj) {
forward_to
ã¯ããªããžã§ã¯ãã®ããŒã«ãŒã¯ãŒãã«ãç§»åã¢ãã¬ã¹ããæ ŒçŽãããããæãéèŠãªéšåã§ãã ããã¯æ¬¡ã®ã¹ãããã§å¿
èŠã«ãªããŸãã
3.4ã ãã€ã³ã¿ãŒãä¿®æ£ãã
ããã§ãããŒããããäžåºŠèª¿ã¹ãŠã次ã®ã¢ã«ãŽãªãºã ã«åŸã£ãŠãã¹ãŠã®ãªã³ã¯ãæ°ããã¢ãã¬ã¹ã§æžãæããå¿
èŠããããŸãã

{ GCTraceTime(Info, gc) time("Step 3: Adjust pointers", NULL);
ã·ããããããªããžã§ã¯ããžã®åç
§ã«ã¯ãããŒãèªäœã®ãªããžã§ã¯ãããã®çºä¿¡ããŸãã¯GCã«ãŒãããã®çºä¿¡ã®2çš®é¡ããããŸãã äž¡æ¹ã®ãªã³ã¯ã¯ã©ã¹ãæŽæ°ããå¿
èŠããããŸãã äžéšã®ä¿åã©ãã«ã«ã¯ãªããžã§ã¯ããžã®åç
§ãä¿åããããããæŽæ°ããããã«äŸé Œããå¿
èŠããããŸãã PreservedMarks
ã¯ããããè¡ãæ¹æ³ãç¥ã£ãŠããŸããããã¯ããªããžã§ã¯ãã®ããŒãã³ã°ã¯ãŒãã§ãä¿åããå Žæãšåãå Žæã«ãããŒã¿ã転éãããããšãæ³å®ããŠããããã§ãã
ã¯ããŒãžã£ãŒã¯2ã€ã®ã¿ã€ãã«åããããŸãããªããžã§ã¯ããååŸããŠã³ã³ãã³ãããã€ãã¹ãããã®ãšããããã®ã¢ãã¬ã¹ãæŽæ°ãããã®ããããŸãã ããã§ãããã©ãŒãã³ã¹ã®å°ããªæé©åãè¡ãããšãã§ããŸãããªããžã§ã¯ããç§»åããªãå Žåãããã€ãã®ã¬ã³ãŒãããŸãšããŠä¿åã§ããŸãã
class EpsilonAdjustPointersOopClosure : public BasicOopIterateClosure { private: template <class T> void do_oop_work(T* p) {
ãã®ã¹ããããå®äºããåŸãåºæ¬çã«æãå£ããŸããããªã³ã¯ã¯ããªããžã§ã¯ãããŸã ååšããªããééã£ããã¢ãã¬ã¹ãæããŸãã ãããä¿®æ£ããŸãããïŒ
3.5ã ãªããžã§ã¯ããç§»åããŸã
ã¢ã«ãŽãªãºã ã«åŸã£ãŠããªããžã§ã¯ããæ°ããã¢ãã¬ã¹ã«ç§»åããæéïŒ

ããŒããå床EpsilonMoveObjectsObjectClosure
ãããã¹ãŠã®çããŠãããªããžã§ã¯ãã«EpsilonMoveObjectsObjectClosure
ã¯ããŒãžã£ãŒãé©çšããŸãã
{ GCTraceTime(Info, gc) time("Step 4: Move objects", NULL);
ãã®çŽåŸã«ãå§çž®ãã€ã³ãããŒãã®ããŒãããã©ãã°ããŠãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãµã€ã¯ã«ãçµäºããçŽåŸã«ããã®å Žæããã¡ã¢ãªãçŽæ¥å²ãåœãŠãããšãã§ããŸãã
ã·ããã¢ã»ã³ããªã§ã¯ãæ¢åã®ãªããžã§ã¯ãã®å
容ãäžæžãã§ããŸãããã¹ãã£ã³ã¯åãæ¹åã«é²ããããäžæžãããããªããžã§ã¯ãã¯æ¢ã«é©åãªå Žæã«ã³ããŒãããŠããããšã«æ³šæããŠãã ããã
åãæœèšã®å€ãå Žæãšæ°ããå Žæã亀差ããå ŽåããããŸãã ããšãã°ã100ãã€ãã®ãªããžã§ã¯ãã8ãã€ãç§»åããå Žåã ã³ããŒæé ã¯ããèªäœã§ããŸãããã¯ãã§ããã亀差ããã³ã³ãã³ããæ£ããã³ããŒããå¿
èŠããããŸãCopy::aligned_*conjoint*_words
泚æããŠCopy::aligned_*conjoint*_words
ã
ã¯ããŒãžã£èªäœã¯ãç§»åããããªããžã§ã¯ããæ°ããã¢ãã¬ã¹ã«ç§»åããã ãã§ãã
class EpsilonMoveObjectsObjectClosure : public ObjectClosure { public: void do_object(oop obj) {
3.6ã ãšãããŒã°
ã¬ããŒãžã³ã¬ã¯ã·ã§ã³ãçµäºããããŒãã¯ã»ãŒäžè²«ããç¶æ
ã«ãªããæåŸã®æåŸã®ä»äžããæ®ããŸãã
{ GCTraceTime(Info, gc) time("Step 5: Epilogue", NULL);
ã©ã³ã¿ã€ã ã®æ®ãã®éšåã«ã¯ãã¢ã»ã³ããªåŸã®æé ãéå§ããå¿
èŠãããããšãéç¥ããŸãã 以åã«ä¿åããç¹å¥ãªããŒã«ãŒã¯ãŒãã埩å
ããŸãã ããŒã«ãŒã«ãŒãã«å¥ããåãã-ããå¿
èŠãããŸããã
ãŸããæ¬åœã«å¿
èŠãªå Žåã¯ãå²ãåœãŠçšã®ã¡ã¢ãªãæ°ãããµã€ãºã«æžãããŠããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã«ã¡ã¢ãªãè¿ãããšãã§ããŸãã
4. GCãVMã«æ¥ç¶ããŸã
4.1ã ã«ãŒããã©ããŒãµã«
VMããç¹å¥ãªå°éå¯èœãªãªã³ã¯ããã€ãã¹ããå¿
èŠãããããšãèŠããŠããŸããïŒ åç¹å¥ãªVMãµãã·ã¹ãã ã«ãä»ã®Javaãªããžã§ã¯ãããé ããããªã³ã¯ããã€ãã¹ããããã«äŸé Œã§ããŸãã çŸåšã®ãããã¹ãããã®ãã®ãããªã«ãŒãèŠçŽ ã®å®å
šãªãªã¹ãã¯ã次ã®ããã«ãªããŸãã
void EpsilonHeap::do_roots(OopClosure* cl) {
, . GC .
4.2ã
GC , VM . Hotspot VM_Operation
, GC VM- :
, GC â , .
4.3ã
, GC , , GC , . , allocate_work
, GC :
HeapWord* EpsilonHeap::allocate_or_collect_work(size_t size) { HeapWord* res = allocate_work(size); if (res == NULL && EpsilonSlidingGC) { vmentry_collect(GCCause::_allocation_failure); res = allocate_work(size); } return res; }
以äžã§ãïŒ
5.
OpenJDK.
$ hg clone https://hg.openjdk.java.net/jdk/jdk/ jdk-jdk $ cd jdk-jdk $ curl https://shipilev.net/jvm/diy-gc/webrev/jdk-jdk-epsilon.changeset | patch -p1
OpenJDK :
$ ./configure --with-debug-level=fastdebug $ make images
:
$ build/linux-x86_64-server-fastdebug/images/jdk/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonSlidingGC -version openjdk version "13-internal" 2019-09-17 OpenJDK Runtime Environment (build 13-internal+0-adhoc.shade.jdk-jdk-epsilon) OpenJDK 64-Bit Server VM (build 13-internal+0-adhoc.shade.jdk-jdk-epsilon, mixed mode, sharing
6.
, GC ? :
- . . Hotspot , JVM fastdebug , GC.
- . , . , ( ) , .
- . , , , . - , .
, , :
$ CONF=linux-x86_64-server-fastdebug make images run-test TEST=gc/epsilon/ Building targets 'images run-test' in configuration 'linux-x86_64-server-fastdebug' Test selection 'gc/epsilon/', will run: * jtreg:test/hotspot/jtreg/gc/epsilon Running test 'jtreg:test/hotspot/jtreg/gc/epsilon' Passed: gc/epsilon/TestAlwaysPretouch.java Passed: gc/epsilon/TestAlignment.java Passed: gc/epsilon/TestElasticTLAB.java Passed: gc/epsilon/TestEpsilonEnabled.java Passed: gc/epsilon/TestHelloWorld.java Passed: gc/epsilon/TestLogTrace.java Passed: gc/epsilon/TestDieDefault.java Passed: gc/epsilon/TestDieWithOnError.java Passed: gc/epsilon/TestMemoryPools.java Passed: gc/epsilon/TestMaxTLAB.java Passed: gc/epsilon/TestPrintHeapSteps.java Passed: gc/epsilon/TestArraycopyCheckcast.java Passed: gc/epsilon/TestClasses.java Passed: gc/epsilon/TestUpdateCountersSteps.java Passed: gc/epsilon/TestDieWithHeapDump.java Passed: gc/epsilon/TestByteArrays.java Passed: gc/epsilon/TestManyThreads.java Passed: gc/epsilon/TestRefArrays.java Passed: gc/epsilon/TestObjects.java Passed: gc/epsilon/TestElasticTLABDecay.java Passed: gc/epsilon/TestSlidingGC.java Test results: passed: 21 TEST SUCCESS
? fastdebug . ? - .
7.
- spring-petclinic , Apache Bench GC! , , GC .
: -Xlog:gc -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonSlidingGC
:
:
Heap: 20480M reserved, 20480M (100.00%) committed, 19497M (95.20%) used GC(2) Step 0: Prologue 2.085ms GC(2) Step 1: Mark 51.005ms GC(2) Step 2: Calculate new locations 71.207ms GC(2) Step 3: Adjust pointers 49.671ms GC(2) Step 4: Move objects 22.839ms GC(2) Step 5: Epilogue 1.008ms GC(2) GC Stats: 70561 (8.63%) reachable from roots, 746676 (91.37%) reachable from heap, 91055 (11.14%) moved, 2237 (0.27%) markwords preserved GC(2) Heap: 20480M reserved, 20480M (100.00%) committed, 37056K (0.18%) used GC(2) Lisp2-style Mark-Compact (Allocation Failure) 20479M->36M(20480M) 197.940ms
200 ? GC! , . , , : ( â , ). - ( ).
, GC . , -Xlog:gc -XX:+UseSerialGC
â , , :
GC(46) Pause Young (Allocation Failure) 575M->39M(1943M) 2.603ms GC(47) Pause Young (Allocation Failure) 575M->39M(1943M) 2.606ms GC(48) Pause Young (Allocation Failure) 575M->39M(1943M) 2.747ms GC(49) Pause Young (Allocation Failure) 575M->39M(1943M) 2.578ms
, 2 . , , GC . -Xlog:gc -XX:+UseSerialGC
, , :
GC(3) Pause Full (Allocation Failure) 16385M->34M(18432M) 1969.694ms GC(4) Pause Full (Allocation Failure) 16385M->34M(18432M) 2261.405ms GC(5) Pause Full (Allocation Failure) 16385M->34M(18432M) 2327.577ms GC(6) Pause Full (Allocation Failure) 16385M->34M(18432M) 2328.976ms
, . .
8. ?
. , GC OpenJDK â , , .
:
. , // . . , , « » , , .
GC, java.lang.ref.Reference.referent
â Java-, , , - . FinalReference
, .
ReferenceProcessor
/ / .
VM. VM, , , . . , , , - , .
. â , GC, . , , , .
mark-compact GC Full GC fallbacks Shenandoah ( OpenJDK 8) G1 ( OpenJDK 10, JEP 307: «Parallel Full GC for G1» ).
. , «» , , , - . . , .
. , , , . , «» â «» «» , .
- GC Handbook .
9.
? GC â , , , GC.
, - GC . , , GC (, Serial GC Parallel GC), .
åºåã®åã , 5-6 2019, JPoint â Java-. â OpenJDK, GraalVM, Kotlin . .