рдкреНрд░рджрд░реНрд╢рди рдХреЗ рддрд╣рдд рдЦрд╛рди рдкрдВрдЦреЛрдВ рдореЗрдВ рдЗрдВрддрдЬрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВ

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рддрд╣рдд рд░рдЦреА рдЧрдИ рдЦрджрд╛рдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛, рд╕рд╛рде рд╣реА рдЙрдирдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ (рдЕрдзрд┐рдорд╛рдирддрдГ рд╡рд┐рд╕реНрдлреЛрдЯ рд╕реЗ рдкрд╣рд▓реЗ) рдФрд░ рдирд┐рдкрдЯрд╛рдиред


рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рддрд╕реНрд╡реАрд░

рдЫрд╡рд┐


рдореЗрд░рд╛ рдХреНрдпрд╛ рд╣реИ?


рдЖрдЗрдП рдХрд┐рд╕реА рднреА рдЬреНрдЮрд╛рди рдХреЗ рдореВрд▓ рдореЗрдВ рдирд┐рд╣рд┐рдд рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░реЗрдВ - рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд╕рд╛рдеред рдкреВрд░реНрд╡рдЬреЛрдВ рдиреЗ рдХрд╣рд╛ рдХрд┐ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдирд╛рдо рд░рдЦрдиреЗ рдХрд╛ рдорддрд▓рдм рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕рдордЭрдирд╛ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рддрд╣рдд рдЦрд╛рдиреЛрдВ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдЧрд▓рддреА рдХреЗ рд╡рд┐рдкрд░реАрдд рд╡реНрдпрдХреНрдд рдХреА рдЬрд╛рддреА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣:


String concat(String... strings) { String result = ""; for (String str : strings) { result += str; } return result; } 

рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдиреМрд╕рд┐рдЦрд┐рдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рднреА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд▓рд╛рдЗрдиреЗрдВ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИрдВ, рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рд▓реВрдк рдореЗрдВ рдЪрдордХрд╛рдиреЗ рдХрд╛ рдорддрд▓рдм рдореМрдЬреВрджрд╛ рд▓рд╛рдЗрди рдХреА рдкреВрдВрдЫ рдореЗрдВ рдбреЗрдЯрд╛ рдЬреЛрдбрд╝рдирд╛ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдирдИ рд▓рд╛рдЗрди рдмрдирд╛рдирд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдЧрд▓рдд рд╣реИрдВ, рддреЛ рдирд┐рд░рд╛рд╢ рдордд рд╣реЛ - "рдЖрдЗрдбрд┐рдпрд╛" рдЖрдкрдХреЛ рддреБрд░рдВрдд рдЦрддрд░реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЪреЗрддрд╛рд╡рдиреА рджреЗрдЧрд╛, рдФрд░ "рд╕реЛрдирд╛рд░" рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЖрдкрдХреА рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдореЗрдВ рдмрд╛рдврд╝ рдЖ рдЬрд╛рдПрдЧреАред


рд▓реЗрдХрд┐рди рдпрд╣ рдХреЛрдб рдмрд╣реБрдд рдХрдо рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░реЗрдЧрд╛, рдФрд░ рдЖрдЗрдбрд┐рдпрд╛ ( рд╕рдВрд╕реНрдХрд░рдг 2018.2 рд╕реЗ рдкрд╣рд▓реЗ ) рдЪреБрдк рд╣реЛ рдЬрд╛рдПрдЧрд╛:


 Long total = 0L; List<Long> totals = query.getResultList(); for (Long element : totals) { total += element == null ? 0 : element; } 

рдпрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рди рд╣реИ: рд╕рд░рд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рд░реИрдкрд░ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ 5 рдЗрдХрд╛рдЗрдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рдирдпрд╛ рдЖрд╡рд░рдг рдмрдирд╛рдирд╛ рдФрд░ рдЙрд╕рдореЗрдВ рд╕рдВрдЦреНрдпрд╛ 6 рд▓рд┐рдЦрдирд╛ред


рдпрд╣рд╛рдБ рдордЬрд╝рд╛рдХ рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдХреЗ рджреЛ рдЕрднреНрдпрд╛рд╡реЗрджрди рдХреЗ рдЬрд╛рд╡рд╛ рдореЗрдВ рдореМрдЬреВрдж рд╣реИ - рд╕рд░рд▓ рдФрд░ рд╡рд╕реНрддреБ, рд╕рд╛рде рд╣реА рд╕рд╛рде рднрд╛рд╖рд╛ рджреНрд╡рд╛рд░рд╛ рдЙрдирдХрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдкрд╛рдВрддрд░рдгред рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ, рдХрдИ рдиреМрд╕рд┐рдЦрд┐рдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЛрдЪрддреЗ рд╣реИрдВ: "рдареАрдХ рд╣реИ, рдирд┐рд╖реНрдкрд╛рджрди рдХрд┐рд╕реА рддрд░рд╣ рдЙрдиреНрд╣реЗрдВ рдЦреБрдж рд╕реЗ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ, рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рд╕рдВрдЦреНрдпрд╛ рд╣реИред"


рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИред рдмреЗрдВрдЪрдорд╛рд░реНрдХ рд▓реЗрдВ рдФрд░ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рддрд░реАрдХреЗ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:


рдЕрдЪрд╛рдирдХ, рдпрд╣ рдмрд╣реБрдд рд╕рд╕реНрддрд╛ рдирд┐рдХрд▓рд╛, (рдмрд╛рдж рдореЗрдВ рдЬреЗрдбреАрдХреЗ 11, рдЬрдм рддрдХ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрдиреНрдпрдерд╛ рдирд╣реАрдВ рдХрд╣рд╛ рдЧрдпрд╛)
  (size) Mode Cnt Score Error Units wrapper 10 avgt 100 23,5 ┬▒ 0,1 ns/op wrapper 100 avgt 100 352,3 ┬▒ 2,1 ns/op wrapper 1000 avgt 100 4424,5 ┬▒ 25,2 ns/op wrapper 10 avgt 100 0 ┬▒ 0 B/op wrapper 100 avgt 100 1872 ┬▒ 0 B/op wrapper 1000 avgt 100 23472 ┬▒ 0 B/op 

рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкреНрд░рдХрд╛рд░ рд╕реЗ рддреБрд▓рдирд╛ рдХрд░реЗрдВ:


 primitive 10 avgt 100 6,4 ┬▒ 0,0 ns/op primitive 100 avgt 100 39,8 ┬▒ 0,1 ns/op primitive 1000 avgt 100 252,5 ┬▒ 1,3 ns/op primitive 10 avgt 100 0 ┬▒ 0 B/op primitive 100 avgt 100 0 ┬▒ 0 B/op primitive 1000 avgt 100 0 ┬▒ 0 B/op 

рдпрд╣рд╛рдВ рд╕реЗ рд╣рдо рдкреНрд░рджрд░реНрд╢рди рдХреЗ рддрд╣рдд рдЦрд╛рдиреЛрдВ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ - рдпрд╣ рд╡рд╣ рдХреЛрдб рд╣реИ рдЬреЛ рдЖрдВрдЦ рдХреЛ рдкрдХрдбрд╝рддрд╛ рдирд╣реАрдВ рд╣реИ, рд╕реНрдереИрддрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдгрдХрд░реНрддрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдХрдо рд╕реЗ рдХрдо (рдЙрд╕ рд╕рдордп рдЬрдм рдЖрдк рдЗрд╕рдХреЗ рдкрд╛рд░ рдЖрдП рдереЗ) рдХрд╛ рдкрддрд╛ рдирд╣реАрдВ рд▓рдЧрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХреБрдЫ рдЙрдкрдпреЛрдЧреЛрдВ рдореЗрдВ рдзреАрдорд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЬрдмрдХрд┐ рд░рд╛рд╢рд┐ резреи objects рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ рдФрд░ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдХреИрд╢ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ Long рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреЗрд╡рд▓ рек рдЧреБрдирд╛ рдзреАрдореА рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЖрдХрд╛рд░ 100 рдХреА рдПрдХ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП, рдЧрддрд┐ рд▓рдЧрднрдЧ 10 рдЧреБрдирд╛ рдХрдо рд╣реИред


рдмрдбрд╝реА рдЫреЛрдЯреА рдмрд╛рддреЗрдВ


рдХрднреА-рдХрднреА рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рдмрджрд▓рд╛рд╡, рдЬреЛ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдЕрд░реНрде рдХреЛ рд▓рдЧрднрдЧ рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рдХреБрдЫ рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдПрдХ рдордЬрдмреВрдд рдмреНрд░реЗрдХ рдмрди рдЬрд╛рддрд╛ рд╣реИред


рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдХреЛрдб рд╣реИ:


 // org.springframework.data.convert.CustomConversions$ConversionTargetsCache Map<Object, TypeInformation<?>> cache = new ConcurrentHashMap<>(); private TypeInformation<?> getFromCacheOrCreate(Alias alias) { TypeInformation<?> info = cache.get(alias); if (info == null) { info = getAlias.apply(alias); cache.put(alias, info); } return info; } 

рд╡рд┐рдзрд┐ рд▓реЙрдЬрд┐рдХ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ?


рдЬрд╛рд╕реВрд╕реА рдХрд░рдиреЗ рдореЗрдВ рдЬрд▓реНрджрдмрд╛рдЬреА рди рдХрд░реЗрдВ, рд╕реЛрдЪреЗрдВ

рдпрд╣ рд╣реИ ConcurrentHashMap::computeIfAbsent !


рд╣рдорд╛рд░реЗ рдкрд╛рд╕ "рдЖрда" рд╣реИ рдФрд░ рд╣рдо рдХреВрд▓ рдХреЛ рдХреЛрдб рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ: рдПрдХ рдХреЗ рд╕рд╛рде 6 рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдмрджрд▓реЗрдВ, рдХреЛрдб рдХреЛ рдЫреЛрдЯрд╛ рдФрд░ рд╕рдордЭрдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рдмрдирд╛ред рд╡реИрд╕реЗ, рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХреЗ рдкрд╛рд░рдЦреА рд╕рдВрднрд╡рддрдГ рдПрдХ рдФрд░ рд╕реБрдзрд╛рд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ ConcurrentHashMap::computeIfAbsent рд╕рд╛рде рд▓рд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж;


рдЖрдЗрдП рдПрдХ рдорд╣рд╛рди рд╡рд┐рдЪрд╛рд░ рдХреЛ рд╕рд╛рдХрд╛рд░ рдХрд░реЗрдВ:


 // org.springframework.data.convert.CustomConversions$ConversionTargetsCache Map<Object, TypeInformation<?>> cache = new ConcurrentHashMap<>(); private TypeInformation<?> getFromCacheOrCreate(Alias alias) { return cache.computeIfAbsent(alias, getAlias); } 

рдЗрдХрдЯреНрдард╛ рдХрд┐рдпрд╛, рд╢реБрд░реВ рдХрд┐рдпрд╛, рд░реЛрдпрд╛

рдкреВрд░реНрдг рдЖрдХрд╛рд░ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдЪрд┐рддреНрд░ рдкрд░ рд░рд╛рдЗрдЯ-рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ рдФрд░ "рдирдпрд╛ рдЯреИрдм рдореЗрдВ рдЫрд╡рд┐ рдЦреЛрд▓реЗрдВ" рдЪреБрдиреЗрдВ
рдЫрд╡рд┐


рдЬрдмрдХрд┐ рдЖрд╡реЗрджрди рдПрдХ рдзрд╛рдЧреЗ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рдерд╛, рд╕рдм рдХреБрдЫ рдХрдо рдпрд╛ рдЬреНрдпрд╛рджрд╛ рдЕрдЪреНрдЫрд╛ рдерд╛ред рдзрд╛рд░рд╛рдПрдБ рдФрд░ рднреА рдмрджрддрд░ рд╣реЛрддреА рдЧрдИрдВред рдпрд╣ ConcurrentHashMap::computeIfAbsent рдЪрд▓рд╛ рд╣реИ рдХрд┐ ConcurrentHashMap::computeIfAbsent рдЕрд╡рд░реБрджреНрдз рд╣реИ, рднрд▓реЗ рд╣реА рдХреБрдВрдЬреА рдХреЛ рдкрд╣рд▓реЗ рд╣реА рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реЛ ред рдФрд░ рдпрд╣ рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯ рдорд╛рдирдЧреЛ рдореЗрдВ рдХрд╛рдлреА рдмрдЧ рдХрд╛ рдХрд╛рд░рдг рдмрди рдЧрдпрд╛ред


рдЖрдк рдЗрд╕реЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдорд╛рдк ("рдЖрда") рдХреЗ рд╕рд╛рде рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдЙрд╕рдХрд╛ рдирд┐рд╖реНрдХрд░реНрд╖ рд╣реИ:


 Benchmark Mode Cnt Score Error Units 1 thread computeIfAbsent avgt 20 19,405 ┬▒ 0,411 ns/op getAndPut avgt 20 4,578 ┬▒ 0,045 ns/op 2 threads computeIfAbsent avgt 20 66,492 ┬▒ 2,036 ns/op getAndPut avgt 20 4,454 ┬▒ 0,110 ns/op 4 threads computeIfAbsent avgt 20 155,975 ┬▒ 8,850 ns/op getAndPut avgt 20 5,616 ┬▒ 2,073 ns/op 6 threads computeIfAbsent avgt 20 203,188 ┬▒ 10,547 ns/op getAndPut avgt 20 7,024 ┬▒ 0,456 ns/op 8 threads computeIfAbsent avgt 20 302,036 ┬▒ 31,702 ns/op getAndPut avgt 20 7,990 ┬▒ 0,144 ns/op 

рдХреНрдпрд╛ рдЗрд╕реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рджреНрд╡рд╛рд░рд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЧрд▓рддреА рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдореЗрд░реА рд╡рд┐рдирдореНрд░ рд░рд╛рдп рдореЗрдВ, рдирд╣реАрдВ, рдирд╣реАрдВред рдкреНрд░рд▓реЗрдЦрди рдХрд╣рддрд╛ рд╣реИ:


рдЗрд╕ рдереНрд░реЗрдб рдкрд░ рдЕрдиреНрдп рдереНрд░реЗрдбреНрд╕ рджреНрд╡рд╛рд░рд╛ рдХреБрдЫ рдЕрдкрдбреЗрдЯ рдХрд┐рдП рдЧрдП рдЕрдкрдбреЗрдЯ рдСрдкрд░реЗрд╢рдВрд╕ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдмрдХрд┐ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рди рдкреНрд░рдЧрддрд┐ рдкрд░ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЧрдгрдирд╛ рдХрдо рдФрд░ рд╕рд░рд▓ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЗрд╕ рдореИрдк рдХреЗ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдореИрдкрд┐рдВрдЧ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП

рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, ConcurrentHashMap::computeIfAbsent рдЙрд╕ рд╕реЗрд▓ рдХреЛ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдмрд╛рд╣рд░ рдХреА рджреБрдирд┐рдпрд╛ ( ConcurrentHashMap::get ) рдХреЗ рд╡рд┐рдкрд░реАрдд рдХреБрдВрдЬреА рд╣реЛрддреА рд╣реИ, рдЬреЛ рдЖрдо рддреМрд░ рдкрд░ рд╕рдЪ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рд╡рд┐рднрд┐рдиреНрди рдереНрд░реЗрдбреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп рджреМрдбрд╝ рдХреЛ рдЪрдХрдорд╛ рджреЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬрдм рдХреБрдВрдЬреА рдХреЛ рдЕрднреА рддрдХ рдЬреЛрдбрд╝рд╛ рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИред


рджреВрд╕рд░реА рдУрд░, рдСрдкрд░реЗрд╢рди рдХреЗ рд╕рдмрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдореЛрдб рдореЗрдВ, рдореВрд▓реНрдп рдХреА рдЧрдгрдирд╛ рдФрд░ рдХреБрдВрдЬреА рдХреЗ рд╕рд╛рде рдЗрд╕рдХреА рдмрд╛рдЗрдВрдбрд┐рдВрдЧ рдХреЗрд╡рд▓ рдкрд╣рд▓реА рдХреЙрд▓ рдкрд░ рд╣реЛрддреА рд╣реИ, рдФрд░ рдмрд╛рдж рдХреА рд╕рднреА рдХреЙрд▓ рдХреЗрд╡рд▓ рдкрд╣рд▓реЗ рдХреА рдЧрдгрдирд╛ рдХреА рдЧрдИ рд╡реИрд▓реНрдпреВ рд╡рд╛рдкрд╕ рдХрд░рддреА рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдпрд╣ рддрд░реНрдХ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ рддрд╛рдХрд┐ рддрд╛рд▓рд╛ рдмрджрд▓рддреЗ рд╕рдордп рд╣реА рд╕реЗрдЯ рд╣реЛред рдЗрд╕реЗ рдпрд╣рд╛рдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ ред


рд╣рд╛рд▓ рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ (> 8), ConcurrentHashMap::computeIfAbsent рд╣реЛ рдЧрдпрд╛ рд╣реИ:


 JDK 11 Benchmark Mode Cnt Score Error Units 1 thread computeIfAbsent avgt 20 6,983 ┬▒ 0,066 ns/op getAndPut avgt 20 5,291 ┬▒ 1,220 ns/op 2 threads computeIfAbsent avgt 20 7,173 ┬▒ 0,249 ns/op getAndPut avgt 20 5,118 ┬▒ 0,395 ns/op 4 threads computeIfAbsent avgt 20 7,991 ┬▒ 0,447 ns/op getAndPut avgt 20 5,270 ┬▒ 0,366 ns/op 6 threads computeIfAbsent avgt 20 11,919 ┬▒ 0,865 ns/op getAndPut avgt 20 7,249 ┬▒ 0,199 ns/op 8 threads computeIfAbsent avgt 20 14,360 ┬▒ 0,892 ns/op getAndPut avgt 20 8,511 ┬▒ 0,229 ns/op 

рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХреА рдХрдкрдЯрдкреВрд░реНрдгрддрд╛ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ: рд╢рдмреНрджрд╛рд░реНрде рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдмрд╣реБрдд рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рд╣реБрдЖ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ рд╣рдордиреЗ рд╕рд┐рд░реНрдл рдПрдХ рдЕрдзрд┐рдХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛ред рдЙрд╕реА рд╕рдордп, рдЬрдмрдХрд┐ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрдХ рдереНрд░реЗрдб рдореЗрдВ рдЪрд▓рддрд╛ рд╣реИ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓рдЧрднрдЧ рдЕрдВрддрд░ рдорд╣рд╕реВрд╕ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ! рдпрд╣ рдЗрд╕ рддрд░рд╣ рд╣рд╛рдирд┐рд░рд╣рд┐рдд рдкрд░рд┐рд╡рд░реНрддрди рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рд╕реБрдЕрд░ рд╣рдорд╛рд░реЗ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рддрд╣рдд рдореЗрд░рд╛ред


рдореИрдВрдиреЗ 'рд▓рдЧрднрдЧ рдЕрдкрд░рд┐рд╡рд░реНрддрд┐рдд' рдХреНрдпреЛрдВ рд▓рд┐рдЦрд╛

ConcurrentHashMap::computeIfAbsent рд╣рдореЗрд╢рд╛ getAndPut рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд╕рд╛рде рд╡рд┐рдирд┐рдореЗрдп рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ ConcurrentHashMap::computeIfAbsent рдПрдХ рдкрд░рдорд╛рдгреБ рдСрдкрд░реЗрд╢рди рд╣реИред рдЙрд╕реА рдХреЛрдб рдореЗрдВ


 private TypeInformation<?> getFromCacheOrCreate(Alias alias) { TypeInformation<?> info = cache.get(alias); if (info == null) { info = getAlias.apply(alias); cache.put(alias, info); } return info; } 

рдмрд╛рд╣рд░реА рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреА рдХрдореА рдХреЗ рдХрд╛рд░рдг , рдПрдХ рджреМрдбрд╝ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ ред рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди ConcurrentHashMap::computeIfAbsent рдХреЛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ ConcurrentHashMap::computeIfAbsent рджрд┐рдП рдЧрдП рдХреБрдВрдЬреА рдХреЗ рд▓рд┐рдП ConcurrentHashMap::computeIfAbsent рд╣рдореЗрд╢рд╛ рдПрдХ рд╣реА рдорд╛рди рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдПрдХ "рд╕реБрд░рдХреНрд╖рд┐рдд" рджреМрдбрд╝ рд╣реИ, рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЬрд┐рд╕реЗ рд╣рдо рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рд╡рд╣ рд╕рдорд╛рди рдореВрд▓реНрдп 2 рдпрд╛ рдЕрдзрд┐рдХ рдмрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХрд░ рд░рд╣рд╛ рд╣реИред рдпрджрд┐ рдРрд╕реА рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ, рддреЛ рдПрдХ рдпрд╛рдВрддреНрд░рд┐рдХ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рдЯреВрдЯрдиреЗ рд╕реЗ рднрд░рд╛ рд╣реИред рд╕рд╛рд╡рдзрд╛рди!


рдЗрди рд╣рд╛рдереЛрдВ рдиреЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрджрд▓рд╛


рдРрд╕рд╛ рднреА рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдХреЛрдб рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдмрджрд▓рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЪрд╛рдирдХ рдпрд╣ рдзреАрдорд╛ рд╣реЛрдирд╛ рд╢реБрд░реВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред


рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдо рдПрдХ рд╕рд░рдгреА рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдХреЗ рд╕рд╛рде рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╕рдмрд╕реЗ рддрд╛рд░реНрдХрд┐рдХ рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП Collection::addAll рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рджреБрд░реНрднрд╛рдЧреНрдп рд╣реИ - рдпрд╣ рд╕рдВрдЧреНрд░рд╣ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ:


 public interface Collection<E> extends Iterable<E> { boolean addAll(Collection<? extends E> c); } 

рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рд╣реИ Arrays::asList рдореЗрдВ Arrays::asList ред рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рдЬрд╛рдПрдЧрд╛


 boolean addItems(Collection<T> collection) { T[] items = getArray(); return collection.addAll(Arrays.asList(items)); } 

рдкреНрд░реВрдлрд░реАрдбрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди, рдкреНрд░рджрд░реНрд╢рди рдХреЗ рдкреНрд░рддрд┐ рдЬрд╛рдЧрд░реВрдХ рд╕рд╣рдХрд░реНрдореА рд╢рд╛рдпрдж рд╣рдореЗрдВ рдмрддрд╛рдПрдВрдЧреЗ рдХрд┐ рдЗрд╕ рдХреЛрдб рдореЗрдВ рджреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ:


  • рдХрд┐рд╕реА рд╕реВрдЪреА рдореЗрдВ рдПрдХ рд╕рд░рдгреА рд▓рдкреЗрдЯрдирд╛ (рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд╕реНрддреБ)
  • рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдмрдирд╛рдиреЗ рд╡рд╛рд▓рд╛ (рджреВрд╕рд░реА рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд╕реНрддреБ) рдФрд░ рдЙрд╕рд╕реЗ рд╣реЛрдХрд░ рдЧреБрдЬрд░рдирд╛

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, Collection::addAll рдХреЗ рд╕рдВрджрд░реНрдн рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди Collection::addAll рд╣рдо рдЗрд╕реЗ рджреЗрдЦреЗрдВрдЧреЗ:


 public abstract class AbstractCollection<E> implements Collection<E> { public boolean addAll(Collection<? extends E> c) { boolean modified = false; for (E e : c) { if (add(e)) modified = true; } return modified; } } 

рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ рдПрдХ рдЗрдЯрд░реЗрдЯрд░ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рддрддреНрд╡реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд╕реЙрд░реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЕрдиреБрднрд╡реА рдХрд╛рдорд░реЗрдб рдЕрдкрдирд╛ рд╕рдорд╛рдзрд╛рди рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВ:


 boolean addItems(Collection<T> collection) { T[] items = getArray(); return Collections.addAll(collection, items); } 

рдХреЛрдб рдХреЗ рдЕрдВрджрд░, рдХрд╛рдлреА рдЕрдзрд┐рдХ рдЙрддреНрдкрд╛рджрдХ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ :


 public static <T> boolean addAll(Collection<? super T> c, T... elements) { boolean result = false; for (T element : elements) result |= c.add(element); return result; } 

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рджреВрд╕рд░реЗ, рдкрд╛рд╕ рд╕рд╛рдорд╛рдиреНрдп рдЧрд┐рдирддреА рдЪрдХреНрд░ рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рд░рдгрд┐рдпрд╛рдВ рдХреИрд╢ рдореЗрдВ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдлрд┐рдЯ рд╣реЛрддреА рд╣реИрдВ, рдЗрд╕рдХреЗ рддрддреНрд╡ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдореЗрдореЛрд░реА рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИрдВ (рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдХреБрдЫ рдХреИрд╢ рдорд┐рд╕реЗрдЬ рд╣реЛрдВрдЧреЗ), рдФрд░ рдЗрдВрдбреЗрдХреНрд╕ рджреНрд╡рд╛рд░рд╛ рдЙрди рддрдХ рдкрд╣реБрдВрдЪ рдмрд╣реБрдд рддреЗрдЬ рд╣реИред рдЦреИрд░, рдПрдХ рдЖрд╡рд░рдг рд╕реВрдЪреА рднреА рдирд╣реАрдВ рдмрдирд╛рдИ рдЧрдИ рд╣реИред рдпрд╣ рдЕрдЪреНрдЫрд╛ рдФрд░ рдЕрдЪреНрдЫрд╛ рд▓рдЧрддрд╛ рд╣реИред


рдЕрдВрдд рдореЗрдВ, рд╕рд╣рдХрд░реНрдорд┐рдпреЛрдВ рдиреЗ рдЕрд▓реНрдЯреАрдорд╛ рдЕрдиреБрдкрд╛рдд рд░реЗрдЧрдо: рдкреНрд░рд▓реЗрдЦрди рдХрд╛ рд╣рд╡рд╛рд▓рд╛ рджрд┐рдпрд╛ред рдФрд░ рд╡рд╣рд╛рдБ, рд╕рдлреЗрдж рдкрд░ рдЧреНрд░реЗ (рдпрд╛ рдХрд╛рд▓реЗ рдкрд░ рд╣рд░рд╛) рдХрд╣рддреЗ рд╣реИрдВ:


 /** * ... * The behavior of this convenience method is identical to that of * c.addAll(Arrays.asList(elements)), but this method is likely * to run significantly faster under most implementations. <---- * @since 1.5 */ @SafeVarargs public static <T> boolean addAll(Collection<? super T> c, T... elements) { //... } 

рдпрд╣реА рд╣реИ, рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЦреБрдж (рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕ рдкрд░ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрдЧрд░ рдЙрдиреНрд╣реЗрдВ рдирд╣реАрдВ?) рд▓рд┐рдЦреЗрдВ рдХрд┐ рдЕрдзрд┐рдХрд╛рдВрд╢ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╡рд┐рдзрд┐ рдмрд╣реБрдд рддреЗрдЬреА рд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИ ред рдФрд░ рд╡рд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рддреЗрдЬ рд╣реИред рдХрднреА рдХрднреАред


рдмреЗрдВрдЪрдорд╛рд░реНрдХ , рдЬрд┐рд╕реЗ рд╣рдо G8 рдкрд░ HashSet рд▓рд┐рдП рд▓реЙрдиреНрдЪ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕реЗ HashSet рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛:


 Benchmark (collection) (size) Mode Cnt Score Error Units addAll HashSet 10 avgt 100 155,2 ┬▒ 2,8 ns/op addAll HashSet 100 avgt 100 1884,4 ┬▒ 37,4 ns/op addAll HashSet 1000 avgt 100 17917,3 ┬▒ 298,8 ns/op collectionsAddAll HashSet 10 avgt 100 136,1 ┬▒ 0,8 ns/op collectionsAddAll HashSet 100 avgt 100 1538,3 ┬▒ 31,4 ns/op collectionsAddAll HashSet 1000 avgt 100 15168,6 ┬▒ 289,4 ns/op 

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдзрд┐рдХ рдЕрдиреБрднрд╡реА рдХрд╛рдорд░реЗрдб рд╕рд╣реА рдереЗред рд▓рдЧрднрдЧред


рдмрд╛рдж рдХреЗ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 11 рдореЗрдВ) рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдкрджреНрдзрддрд┐ рдХреА рдЪрдордХ рдХреБрдЫ рдлреАрдХреА рдкрдбрд╝ рдЬрд╛рдПрдЧреА:


 Benchmark (collection) (size) Mode Cnt Score Error Units addAll HashSet 10 avgt 100 143,1 ┬▒ 0,6 ns/op addAll HashSet 100 avgt 100 1738,4 ┬▒ 7,3 ns/op addAll HashSet 1000 avgt 100 16853,9 ┬▒ 101,0 ns/op collectionsAddAll HashSet 10 avgt 100 132,1 ┬▒ 1,1 ns/op collectionsAddAll HashSet 100 avgt 100 1661,1 ┬▒ 7,1 ns/op collectionsAddAll HashSet 1000 avgt 100 15450,9 ┬▒ 93,9 ns/op 

рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдХрд┐рд╕реА рднреА "рдмрд╣реБрдд рддреЗрдЬ" рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдФрд░ рдЕрдЧрд░ рд╣рдо ArrayList -a рдХреЗ рд▓рд┐рдП рдкреНрд░рдпреЛрдЧ рджреЛрд╣рд░рд╛рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╡рд┐рдзрд┐ рдмрд╣реБрдд рдЕрдзрд┐рдХ (рдЖрдЧреЗ рдордЬрдмреВрдд) рдЦреЛрдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрддреА рд╣реИ:


 Benchmark (collection) (size) Mode Cnt Score Error Units JDK 8 addAll ArrayList 10 avgt 100 38,5 ┬▒ 0,5 ns/op addAll ArrayList 100 avgt 100 188,4 ┬▒ 7,0 ns/op addAll ArrayList 1000 avgt 100 1278,8 ┬▒ 42,9 ns/op collectionsAddAll ArrayList 10 avgt 100 62,7 ┬▒ 0,7 ns/op collectionsAddAll ArrayList 100 avgt 100 495,1 ┬▒ 2,0 ns/op collectionsAddAll ArrayList 1000 avgt 100 4892,5 ┬▒ 48,0 ns/op JDK 11 addAll ArrayList 10 avgt 100 26,1 ┬▒ 0,0 ns/op addAll ArrayList 100 avgt 100 161,1 ┬▒ 0,4 ns/op addAll ArrayList 1000 avgt 100 1276,7 ┬▒ 3,7 ns/op collectionsAddAll ArrayList 10 avgt 100 41,6 ┬▒ 0,0 ns/op collectionsAddAll ArrayList 100 avgt 100 492,6 ┬▒ 1,5 ns/op collectionsAddAll ArrayList 1000 avgt 100 6792,7 ┬▒ 165,5 ns/op 

рдпрд╣рд╛рдБ рдХреБрдЫ рднреА рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдирд╣реАрдВ рд╣реИ, ArrayList рдПрдХ рд╕рд░рдгреА рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рдиреЗ рджреВрд░ рд╕реЗ Collection::addAll рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ:


 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); modCount++; int numNew = a.length; if (numNew == 0) return false; Object[] elementData; final int s; if (numNew > (elementData = this.elementData).length - (s = size)) elementData = grow(s + numNew); System.arraycopy(a, 0, elementData, s, numNew); <---    size = s + numNew; return true; } 

рдЕрдм рд╡рд╛рдкрд╕ рд╣рдорд╛рд░реЗ рдЦрд╛рдиреЛрдВ рдореЗрдВред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдордиреЗ рдлрд┐рд░ рднреА рдкреНрд░реВрдлрд░реАрдбрд┐рдВрдЧ рдкрд░ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд▓рд┐рдпрд╛ рдФрд░ рдЗрд╕ рдХреЛрдб рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛:


 boolean addItems(Collection<T> collection) { T[] items = getArray(); return Collections.addAll(collection, items); } 

рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП, рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдирдИ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж, рд╡рд┐рдзрд┐ рдХрднреА-рдХрднреА рдЧрд░реНрдо рд╣реЛ рдЬрд╛рддреА рд╣реИ рдФрд░ рдзреАрдорд╛ рд╣реЛрдиреЗ рд▓рдЧрддреА рд╣реИред рд╣рдо рд╕реНрд░реЛрдд рдХреЛрдб рдЦреЛрд▓рддреЗ рд╣реИрдВ - рдХреЛрдб рдирд╣реАрдВ рдмрджрд▓рд╛ред рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рд╕рдорд╛рди рд╣реИред рдФрд░ рдкреНрд░рджрд░реНрд╢рди рдмрд╣реБрдд рдХреБрдЫ рдбреВрдм рдЧрдпрд╛ред рдпрд╣ рдореЗрд░рд╛ рдПрдХ рдФрд░ рдкреНрд░рдХрд╛рд░ рд╣реИред


рдбрд┐рдмрдЧрд░ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░реЗрдВ рдФрд░ рд╕реБрдВрджрд░ рдвреВрдВрдвреЗрдВ:



рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ: рд╣рдордиреЗ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЛ рдирд╣реАрдВ рдмрджрд▓рд╛, рд╕рдВрд╕рд╛рдзрд┐рдд рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рд╣реБрдЖ, рд▓реЗрдХрд┐рди рдЙрдирдХреА рдкреНрд░рдХреГрддрд┐ рдмрджрд▓ рдЧрдИ рдФрд░ рд╣рдорд╛рд░реЗ рдХреЛрдб рдореЗрдВ рдПрдХ рдкреНрд░рджрд░реНрд╢рди рд╕рдорд╕реНрдпрд╛ рд╢реБрд░реВ рд╣реБрдИ:


  Java 8 Java 11  addAll 10 56,9 25,2 ns/op collectionsAddAll 10 352,2 142,9 ns/op addAll 100 159,9 84,3 ns/op collectionsAddAll 100 4607,1 3964,3 ns/op addAll 1000 1244,2 760,2 ns/op collectionsAddAll 1000 355796,9 364677,0 ns/op 

рдмрдбрд╝реЗ рд╕рд░рдгрд┐рдпреЛрдВ рдкрд░, Collections::addAll рдФрд░ Collection::addAll рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░ рдПрдХ рдорд╛рдореВрд▓реА 500 рдЧреБрдирд╛ рд╣реИред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ COWList рдХреЗрд╡рд▓ рдореМрдЬреВрджрд╛ рд╕рд░рдгреА рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХ рдирдпрд╛ рдмрдирд╛рддрд╛ рд╣реИ рдЬрдм рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рд░ рддрддреНрд╡ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ:


 public boolean add(E e) { synchronized (lock) { Object[] es = getArray(); int len = es.length; es = Arrays.copyOf(es, len + 1); <----    es[len] = e; setArray(es); return true; } } 

рдХрд┐рд╕реЗ рджреЛрд╖ рджреЗрдирд╛ рд╣реИ?



рдпрд╣рд╛рдБ рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ Collections::addAll рдХрд┐рд╕реА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреА рд╣реИ, рдЬрдмрдХрд┐ addAll рдкрджреНрдзрддрд┐ addAll рдХреЛрдИ рдирд┐рдХрд╛рдп рдирд╣реАрдВ рд╣реИред рдХреЛрдИ рдирд┐рдХрд╛рдп - рдХреЛрдИ рд╡реНрдпрд╡рд╕рд╛рдп рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП, AbstractCollection::addAll рдореЗрдВ рд╡рд┐рджреНрдпрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд╕рднреА рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдПрд▓реНрдЧреЛрд░рд┐рдердо рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдЕрдзрд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЬреЛ рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рдирд┐рдЪрд▓реЗ рд╕реНрддрд░ рдкрд░ рд╣реИрдВ, рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред


рдЕрдм рдорд╛рдирд╡реАрдп рд░реВрдк рд╕реЗ
  Collection::addAll тАУ   AbstractCollection::addAll тАУ   <---    ArrayList::addAll HashSet::addAll тАУ   <---      COWList::addAll 

рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ


рдЪреВрдВрдХрд┐ рд╣рдо рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рд╕реНрддрд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдореИрдВ рдЖрдкрдХреЛ рдЬреАрд╡рди рд╕реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдКрдВрдЧрд╛ред


рдЪрд▓реЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдмрдЪрдд рдХреЗ рдЗрди рджреЛ рддрд░реАрдХреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╣реИрдВ:


 @Transactional void save(int n) { for (int i = 0; i < n; i++) { SimpleEntity e = new SimpleEntity(); repository.save(e); } } @Transactional void _save(int n) { for (int i = 0; i < n; i++) { SimpleEntity e = new SimpleEntity(); repository.saveAndFlush(e); } } 

рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдЕрд▓рдЧ-рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐


  • рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдПрдХ рд╣реА рдирдВрдмрд░ рдХреА рдЗрдХрд╛рдЗрдпрд╛рдБ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рдПрдВрдЧреА
  • рдпрджрд┐ рдХреБрдВрдЬреА рдЕрдиреБрдХреНрд░рдо рд╕реЗ рд▓реА рдЧрдИ рд╣реИ, рддреЛ рдХреЙрд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╕рдорд╛рди рд╣реЛрдЧреА
  • рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рд╕рдорд╛рди рд╣реИ

SimpleJpaRepository::saveAndFlush рдХреА SimpleJpaRepository::saveAndFlush :


 @Transactional public <S extends T> S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } } @Transactional public <S extends T> S saveAndFlush(S entity) { S result = save(entity); flush(); return result; } @Transactional public void flush() { em.flush(); } 

рдпрд╣рд╛рдБ рдбрд╛рд░реНрдХ рд╕реНрдкреЙрдЯ flush() рд╡рд┐рдзрд┐ рд╣реИред рдХреНрдпреЛрдВ рдЧреВрдВрдЧрд╛? рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ JpaRepository рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдЗрд╕рдХрд╛ рдЦреБрд▓рд╛рд╕рд╛ рдПрдХ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреА рдЧрд▓рддреА рдереАред рдореИрдВ рдЕрдкрдиреЗ рд╡рд┐рдЪрд╛рд░ рдХреЛ рд╕рд╣реА рдард╣рд░рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред рдЖрдорддреМрд░ рдкрд░, рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрд╡рд▓рдкрд░ рджреНрд╡рд╛рд░рд╛ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ EntityManager::flush рдХреЙрд▓ рд╕реНрдкреНрд░рд┐рдВрдЧ рджреНрд╡рд╛рд░рд╛ рдирд┐рдпрдВрддреНрд░рд┐рдд рд▓реЗрдирджреЗрди рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реИ:


 //     @Transactional public void method() { <--  Session::open /*.*/ } <--  Session::flush 

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ: EntityManager Hibernate рдореЗрдВ рд╕рддреНрд░ (рд╕рддреНрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ SessionImpl рд╡рд░реНрдЧ, рдХреНрд░рдорд╢рдГ) рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд JPA рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИред рд╕реНрдкреНрд░рд┐рдВрдЧ рдбреЗрдЯ рдПрдХ рдлреНрд░реЗрдорд╡рд░реНрдХ рд╣реИ рдЬреЛ рдУрдЖрд░рдПрдо рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдЪрд▓рддрд╛ рд╣реИ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рдХреЗ рдКрдкрд░ред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ JpaRepository::saveAndFlush рд╣рдореЗрдВ рдПрдкреАрдЖрдИ рдХреЗ рдирд┐рдЪрд▓реЗ рд╕реНрддрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдХрд╛рд░реНрдп рдирд┐рдореНрди-рд╕реНрддрд░реАрдп рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдЫрд┐рдкрд╛рдирд╛ рд╣реИ (рд╕реНрдерд┐рддрд┐ рдЬреЗрдбрдбреАрдХреЗ рдореЗрдВ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдХрд╣рд╛рдиреА рдХреЗ рд╕рдорд╛рди рд╣реИ)ред
рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЬрдм JpaRepository::saveAndFlush рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ JpaRepository::saveAndFlush рддреЛ рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рдирд┐рдЪрд▓реА рдкрд░рддреЛрдВ рдореЗрдВ рдкрд╣реБрдВрдЪ рдЬрд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдХреБрдЫ рд╣реЛрддрд╛ рд╣реИред


рдЭрд╛рдВрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рд╕рдордп рд▓реЗрдВ, рдЕрдкрдиреЗ рд▓рд┐рдП рд╕реЛрдЪреЗрдВ

рдмреИрдЪреЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рднреЗрдЬрдиреЗ рдХреА рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рдХреА рдХреНрд╖рдорддрд╛ рдЯреВрдЯреА рд╣реБрдИ рд╣реИ, рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ jdbc.batch_size рд╕реЗрдЯрд┐рдВрдЧ, рдЬреЛ рдХрд┐ application.yml рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ:


 spring: jpa: properties: hibernate: jdbc.batch_size: 500 

рд╣рд╛рдЗрдмрд░рдиреЗрдЯ рдХрд╛ рдХрд╛рдо рдШрдЯрдирд╛рдУрдВ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЬрдм рдЖрдк 1000 рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрдЪрд╛рддреЗ рд╣реИрдВ


 @Transactional void save(int n) { for (int i = 0; i < n; i++) { SimpleEntity e = new SimpleEntity(); repository.save(e); } } 

рдХреЙрд▓рд┐рдВрдЧ repository.save(e) ред save repository.save(e) рддреБрд░рдВрдд рдирд╣реАрдВ рдмрдЪрддреА рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдПрдХ рдИрд╡реЗрдВрдЯ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХрддрд╛рд░рдмрджреНрдз рд╣реЛрддрд╛ рд╣реИред рд▓реЗрди-рджреЗрди рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░, рдбреЗрдЯрд╛ рдХреЛ EntityManager::flush рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдорд┐рд▓рд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЖрд╡реЗрд╖рдг / рдЕрдкрдбреЗрдЯ рдХреЛ рдХрдИ jdbc.batch_size рдмрдВрдбрд▓реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдирд╕реЗ рдЕрдиреБрд░реЛрдз рдмрдирд╛рддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, jdbc.batch_size: 500 , рдЗрд╕рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡рд┐рдХрддрд╛ рдореЗрдВ 1000 рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХрд╛ рдорддрд▓рдм рдХреЗрд╡рд▓ 2 рдЕрдиреБрд░реЛрдз рд╣реИрдВред


рд▓реЗрдХрд┐рди рдЪрдХреНрд░ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд╕ рдкрд░ рд╕рддреНрд░ рдХреЗ рдореИрдиреБрдЕрд▓ рдбрд┐рд╕реНрдЪрд╛рд░реНрдЬ рдХреЗ рд╕рд╛рде


 @Transactional void _save(int n) { for (int i = 0; i < n; i++) { SimpleEntity e = new SimpleEntity(); repository.saveAndFlush(e); } } 

рдХрддрд╛рд░ рд╕рд╛рдл рд╣реЛ рдЧрдИ рд╣реИ рдФрд░ 1000 рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рдмрдЪрд╛рдиреЗ рдХрд╛ рдорддрд▓рдм рд╣реИ 1000 рдкреНрд░рд╢реНрдиред


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЖрд╡реЗрджрди рдХреА рдирд┐рдЪрд▓реА рдкрд░рддреЛрдВ рдХреЗ рд╕рд╛рде рд╣рд╕реНрддрдХреНрд╖реЗрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдПрдХ рдЦрд╛рди рдмрди рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рди рдХреЗрд╡рд▓ рдПрдХ рдЙрддреНрдкрд╛рджрдХрддрд╛ рдЦрд╛рди (рджреЗрдЦреЗрдВ рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рдФрд░ рдЗрд╕рдХреЗ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рдЙрдкрдпреЛрдЧ)ред


рдпрд╣ рдХрд┐рддрдирд╛ рдзреАрдорд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ? рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдорд╛рдорд▓рд╛ рд▓реЗ рд▓реЛ (рд╣рдорд╛рд░реЗ рд▓рд┐рдП) - рдбреЗрдЯрд╛рдмреЗрд╕ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд╕рдорд╛рди рд╣реЛрд╕реНрдЯ рдкрд░ рд╣реИред рдореЗрд░рд╛ рдорд╛рдк рдирд┐рдореНрди рдЪрд┐рддреНрд░ рджрд┐рдЦрд╛рддрд╛ рд╣реИ:


  (entityCount) Mode Cnt Score Error Units bulkSave 10 ss 500 16,613 ┬▒ 1,714 ms/op bulkSave 100 ss 500 31,371 ┬▒ 1,453 ms/op bulkSave 1000 ss 500 35,687 ┬▒ 1,973 ms/op bulkSaveUsingFlush 10 ss 500 32,653 ┬▒ 2,166 ms/op bulkSaveUsingFlush 100 ss 500 61,983 ┬▒ 6,304 ms/op bulkSaveUsingFlush 1000 ss 500 184,814 ┬▒ 6,976 ms/op 

рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдпрджрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдПрдХ рджреВрд░рд╕реНрде рд╣реЛрд╕реНрдЯ рдкрд░ рд╕реНрдерд┐рдд рд╣реИ, рддреЛ рдбреЗрдЯрд╛ рд╡реЙрд▓реНрдпреВрдо рдмрдврд╝рдиреЗ рдХреЗ рд╕рд╛рде рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдХреА рд▓рд╛рдЧрдд рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдХрдо рдХрд░ рджреЗрдЧреАред


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЕрдореВрд░реНрддрддрд╛ рдХреЗ рдЧрд▓рдд рд╕реНрддрд░ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдЯрд╛рдЗрдо рдмрдо рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╡реИрд╕реЗ, рдореЗрд░реЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рдореИрдВрдиреЗ StringBuilder -рдП рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рдкреНрд░рдпрд╛рд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХреА рдереА: рд╡рд╣рд╛рдВ рдореИрдВ рдХреЛрдб рдХреЗ рдЕрдзрд┐рдХ рд╕рд╛рд░ рд╕реНрддрд░ рдореЗрдВ рдЖрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╕рдордп рдЕрд╕рдлрд▓ рд░рд╣рд╛ рдерд╛ред


рдорд╛рдЗрдирдлреАрд▓реНрдб рд╕реАрдорд╛рдПрдБ


рдЪрд▓реЛ рдПрдХ рд╕реИрдкрд░ рдЦреЗрд▓рддреЗ рд╣реИрдВ? рдореЗрд░рд╛ рдЦреЛрдЬреЗрдВ:


 // org.springframework.cache.interceptor.CacheAspectSupport Object generateKey(CacheOperationContext ctx, Object result) { Object key = ctx.generateKey(result); Assert.notNull(key, "Null key ..." + context.metadata.operation); // ... return key; } 

рдорд┐рд▓ рдЧрдпрд╛? рд╕рд╣реА рдЙрддреНрддрд░ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВред
  | \ / // org.springframework.cache.interceptor.CacheAspectSupport | \ / Object generateKey(CacheOperationContext ctx, Object result) { Object key = ctx.generateKey(result); | \ / Assert.notNull(key, "Null key ..." + context.metadata.operation); return key; } 

"рдХреНрдпрд╛ рддреБрдо рдореБрдЭрд╕реЗ рдордЬрд╛рдХ рдХрд░ рд░рд╣реЗ рд╣реЛ?" рдЖрд▓реЛрдЪрдХ рдиреЗ рдХрд╣рд╛ред "рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдХреЗрд╡рд▓ рджреЛ рд░реЗрдЦрд╛рдУрдВ рдХрд╛ рдПрдХ рдЧрдбрд╝рдмрдбрд╝ рд╣реИ? рдЦреВрдиреА рдИ рдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИ?" рдореБрдЭреЗ рдЗрд╕ рддрдереНрдп рдкрд░ рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдореИрдВрдиреЗ рди рдХреЗрд╡рд▓ рддрд╛рд░реЛрдВ рдХреЗ gluing рдкрд░ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓рд╛, рдмрд▓реНрдХрд┐ рд╡рд░реНрдЧ рдХрд╛ рдирд╛рдо рдФрд░ рд╡рд┐рдзрд┐ рдХрд╛ рдирд╛рдо рднреА рдмрддрд╛рдпрд╛ред рджрд░рдЕрд╕рд▓, рдЧреНрд▓реВрдЗрдВрдЧ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХрд╛ рдЦрддрд░рд╛ рдЦреБрдж рдХреЛ рдЧреНрд▓реВрдЗрдВрдЧ рдХрд░рдиреЗ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдХреИрд╢ рдХреЗ рд▓рд┐рдП рдХреБрдВрдЬреА рдмрдирд╛рддрд╛ рд╣реИ, рдпрд╛рдиреА рдХреБрдЫ рдирд┐рд╢реНрдЪрд┐рдд рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЗрд╕ рдкрджреНрдзрддрд┐ рддрдХ рдмрд╣реБрдд рд╕реА рдкрд╣реБрдВрдЪ рд╣реЛрдЧреА, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдвреЗрд░ рд╕рд╛рд░реА рдЧрд╛рд░рдмреЗрдЬ рд▓рд╛рдЗрдиреЗрдВред
рдЗрд╕рд▓рд┐рдП, рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдХреЗрд╡рд▓ рддрднреА рдмрдирд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм рдпрд╣ рддреНрд░реБрдЯрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдлреЗрдВрдХ рджреА рдЬрд╛рдП:


 // org.springframework.cache.interceptor.CacheAspectSupport Object generateKey(CacheOperationContext ctx, Object result) { Object key = ctx.generateKey(result); if (key == null) { throw new IAE("Null key ..." + context.metadata.operation); } // ... return key; } 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдорд╛рдЗрдирдлреАрд▓реНрдбреНрд╕ рдХреА рд╕реАрдорд╛рдПрдВ рд╣реИрдВ - рдпрд╣ рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛, рд╡рд┐рдзрд┐ рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдЖрд╡реГрддреНрддрд┐, рдЖрджрд┐ рдорд╛рддреНрд░рд╛рддреНрдордХ рд╕рдВрдХреЗрддрдХ рд╣реИрдВ, рдЬреЛ рдкрд╣реБрдВрдЪрдиреЗ рдФрд░ рдЙрд╕рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛрдиреЗ рдкрд░ рдПрдХ рдорд╛рдореВрд▓реА рдЦрд╛рдореА рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдк рд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реЛ рдЬрд╛рддреА рд╣реИред


рджреВрд╕рд░реА рдУрд░, рдпрд╣ рд╡рд╣ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкреНрд░рддрд┐рдЪреНрдЫреЗрджрди рдореЗрдВ рдХреЛрдб рдХреА рдЬрдЯрд┐рд▓рддрд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг (рдФрд╕рдд рджрд░реНрдЬреЗ рдХрд╛) рд╕реБрдзрд╛рд░ рдирд╣реАрдВ рджреЗрддреА рд╣реИред


рдпрд╣ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдирд┐рд╖реНрдХрд░реНрд╖ рд╣реИ: рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдзреЛрдЦрд╛ рдмреБрд░рд╛рдИ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдХреЛрдб рдХреА рдЕрд░реНрдерд╣реАрди рдЬрдЯрд┐рд▓рддрд╛ рд╣реЛ рдЬрд╛рддреА рд╣реИред 100 рдореЗрдВ рд╕реЗ 99 рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдо рдХреБрдЫ рднреА рдирд╣реАрдВ рдЬреАрддрддреЗ рд╣реИрдВред


рдпрд╣ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╣рдореЗрд╢рд╛ рд╣реЛрддрд╛ рд╣реИ


рдПрдХ рд╕реМрд╡рд╛рдВ рдорд╛рдорд▓рд╛


рдпрд╣рд╛рдБ рдХреЛрдб рд╣реИ рдХрд┐ рдирд┐рдЯреНрдЬрд╝реЗрди рд╡рдХрд╛рд░реНрдЯ рдЕрдкрдиреЗ рд▓реЗрдЦ рдореЗрдВ рджреЗрддрд╛ рд╣реИ рд╡рд╛рд╖реНрдкрд╢реАрд▓ рдиреЗ рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд┐рдпрд╛ :


 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Thread) public class LoopyBenchmarks { @Param({ "32", "1024", "32768" }) int size; byte[] bunn; @Setup public void prepare() { bunn = new byte[size]; } @Benchmark public void goodOldLoop(Blackhole fox) { for (int y = 0; y < bunn.length; y++) { // good old C style for (the win?) fox.consume(bunn[y]); } } @Benchmark public void sweetLoop(Blackhole fox) { for (byte bunny : bunn) { // syntactic sugar loop goodness fox.consume(bunny); } } } 

рдЬрдм рд╣рдо рдЕрдиреБрднрд╡ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрдХ рд╕рд░рдгреА рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рдиреЗ рдХреЗ рджреЛ рддрд░реАрдХреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рдЕрджреНрднреБрдд рдЕрдВрддрд░ рдХреА рдЦреЛрдЬ рдХрд░реЗрдВрдЧреЗ:


 Benchmark (size) Score Score error Units goodOldLoop 32 46.630 0.097 ns/op goodOldLoop 1024 1199.338 0.705 ns/op goodOldLoop 32768 37813.600 56.081 ns/op sweetLoop 32 19.304 0.010 ns/op sweetLoop 1024 475.141 1.227 ns/op sweetLoop 32768 14295.800 36.071 ns/op 

рдпрд╣рд╛рдВ, рдПрдХ рдЕрдиреБрднрд╡рд╣реАрди рдбреЗрд╡рд▓рдкрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдФрд░ рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдирд┐рд╖реНрдХрд░реНрд╖ рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИ: рдПрдХ рдЧрд┐рдирддреА рдЪрдХреНрд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдирдП рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░рдгреА рд╕реЗ рдЧреБрдЬрд░рдирд╛ред рдпрд╣ рдЧрд▓рдд рдирд┐рд╖реНрдХрд░реНрд╖ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ goodOldLoop рд╡рд┐рдзрд┐ рдХреЛ goodOldLoop рдмрджрд▓рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ:


 @Benchmark public void goodOldLoopReturns(Blackhole fox) { byte[] sunn = bunn; // make a local copy of the field for (int y = 0; y < sunn.length; y++) { fox.consume(sunn[y]); } } 

рдФрд░ рдЗрд╕рдХрд╛ рдкреНрд░рджрд░реНрд╢рди "рддреЗрдЬ" sweetLoop рд╡рд┐рдзрд┐ рдХреЗ sweetLoop рд╣реИ:


 Benchmark (size) Score Score error Units goodOldLoopReturns 32 19.306 0.045 ns/op goodOldLoopReturns 1024 476.493 1.190 ns/op goodOldLoopReturns 32768 14292.286 16.046 ns/op sweetLoop 32 19.304 0.010 ns/op sweetLoop 1024 475.141 1.227 ns/op sweetLoop 32768 14295.800 36.071 ns/op 

Blackhole::consume :


 //... public volatile byte b1, b2; public volatile BlackholeL2 nullBait = null; /** * Consume object. This call provides a side effect preventing JIT to eliminate dependent computations. * * @param b object to consume. */ public final void consume(byte b) { if (b == b1 & b == b2) { // SHOULD NEVER HAPPEN nullBait.b1 = b; // implicit null pointer exception } } 

, , . goodOldLoop this.bunn , for-each , (, Java Concurrency In Practice " "). .


: " ? , Blackhole::consume тАФ JMH . , , ?"


:


 byte[] bunn; public void goodOldLoop(Blackhole fox) { for (int y = 0; y < bunn.length; y++) { fox.consume(bunn[y]); } } 

? ? , :


 E[] bunn; public void forEach(Consumer<E> fox) { for (int y = 0; y < bunn.length; y++) { fox.consume(bunn[y]); } } 

Iterable::forEach ! , , , ( JDK 13):


 //ArrayList public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); final int expectedModCount = modCount; final Object[] es = elementData; final int size = this.size; for (int i = 0; modCount == expectedModCount && i < size; i++) action.accept(elementAt(es, i)); if (modCount != expectedModCount) throw new ConcurrentModificationException(); } //Arrays$ArrayList public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); for (E e : a) { action.accept(e); } } //CopyOnWriteArrayList public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); for (Object x : getArray()) { @SuppressWarnings("unchecked") E e = (E) x; action.accept(e); } } //ArrayDeque public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); final Object[] es = elements; for (int i = head, end = tail, to = (i <= end) ? end : es.length; ; i = 0, to = end) { for (; i < to; i++) action.accept(elementAt(es, i)); if (to == end) { if (end != tail) throw new ConcurrentModificationException(); break; } } } 

, . , Collections.nCopies()::forEach :


 @Override public void forEach(final Consumer<? super E> action) { Objects.requireNonNull(action); for (int i = 0; i < this.n; i++) { action.accept(this.element); } } 

, . . this.n this.element :


 private static class CopiesList<E> extends AbstractList<E> implements RandomAccess, Serializable { final int n; final E element; CopiesList(int n, E e) { assert n >= 0; this.n = n; element = e; } 

, , @Stable .


: 99 100 , , 1 100, . , .


" volatile".



, :


 //java.lang.Integer @HotSpotIntrinsicCandidate public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } 

- , ( java.lang.Integer , java.lang.Long , java.lang.Short , java.lang.Byte , java.lang.Character ). , ,


 Integer intgr = Integer.valueOf(42); 

.


:


 Integer intgr = new Integer(42); 

, , Integer::valueOf .


: . , , "" ( ). , , Integer::valueOf . " " .


. , . , . , , .

Source: https://habr.com/ru/post/hi443206/


All Articles