Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
令和最新版 PHP メモリ管理術
Search
memory
PRO
February 11, 2024
6
4k
令和最新版 PHP メモリ管理術
PHP カンファレンス関西 2024
PHP Memory Management in Reiwa
memory
PRO
February 11, 2024
Tweet
Share
More Decks by memory
See All by memory
PHP でアセンブリ言語のように書く技術
memory1994
PRO
1
160
PHP でアセンブリっぽく書く技術
memory1994
PRO
1
110
How to implement a RubyVM with PHP?
memory1994
PRO
3
2.3k
二郎系ラーメンのコールで学ぶ AST 解析
memory1994
PRO
8
2.2k
RubyVM を PHP で実装する 〜Hello World を出力するまで〜
memory1994
PRO
1
730
技術的負債が生まれる背景を理解して,アーリーからレイター向けの根本的なアプローチを考える
memory1994
PRO
23
8.9k
激辛のすゝめ
memory1994
PRO
1
550
RubyVM を PHP で実装する 〜Hello World を出力するまで〜
memory1994
PRO
1
6.3k
本当の FizzBuzz をお見せします
memory1994
PRO
1
2.1k
Featured
See All Featured
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
Producing Creativity
orderedlist
PRO
341
39k
For a Future-Friendly Web
brad_frost
175
9.4k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
42
2.2k
Product Roadmaps are Hard
iamctodd
PRO
49
11k
Embracing the Ebb and Flow
colly
84
4.5k
Practical Orchestrator
shlominoach
186
10k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
27
2k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
A Philosophy of Restraint
colly
203
16k
Navigating Team Friction
lara
183
14k
Transcript
ΊΓʔ ྩ࠷৽൛ PHP ϝϞϦཧज़ PHP ΧϯϑΝϨϯε ؔ 2024
ΊΓʔ m3m0r7 memory1994 m3m0r7 1994 5 ݄ੜ·ΕɻෳͷελʔτΞοϓ ্اۀͰιϑτΣΞΤϯδχΞɼΤϯ
δχΞϦϯάϚωʔδϟʔɼςοΫϦʔυɼ ࣥߦһ CTO ͷܦݧΛܦΔɻ2023 7 ݄ ΑΓגࣜձࣾΤϯϖΠͰιϑτΣΞΤϯδ χΞͱͯ͠ैࣄɻಉ 10 ݄ΑΓΤϯδχΞ ϦϯάϚωʔδϟʔɻ
ϝϞϦͳͥΓͳ͘ͳΔͷ͔ ϝϞϦ֬อͷ͘͠Έ ϝϞϦফඅྔΛݮ͢Δʹ ͘͡
Έͳ͞Μɼૺ۰ͨ͜͠ͱ͋Γ·͔͢
ϝϞϦ͕Γͳ͍ͳΒ ૿͍͍ͤ͡Όͳ͍
ini_set('memory_limit', '-1')
…͋·Γڧ͍ݴ༿Λݣ͏ͳΑ ऑ͘ݟ͑Δͧ ʢίʔυʣ
…
͜͜Ͱɼٙʹࢥͬͨํଟ͍Ͱ͠ΐ͏
ʮͳͥɼPHP ϝϞϦ͕Γͳ͘ͳΔͷ͔ʯ
ཧ༝୯७໌շͰ͢
ͦΕɼΓͳ͘ͳΔ͘Β͍ ϝϞϦΛ͍ͬͯΔ͔ΒͰ͢
ྫ͑͜͏͍ͬͨίʔυ ݟͨ͜ͱ͋Γ·͔͢ʁ
͜Ε࣮ɼΊͪΌͪ͘ΌϝϞϦ͍·͢
࣮ࡍʹࢼͯ͠Έ·͠ΐ͏
ͪͳΈʹɼ࣍ͷίʔυ ϝϞϦΛΊͬͪΌ͍·͢
ࣄલʹ mk fi le 2M template_ fi le.tpl
Λ࣮ߦ͓͖ͯ͠·͢
ʮ͡Ό͊ɼͲ͏ͨ͠Β͍͍ͷ… memory_limit ૿͢Ҏ֎ʹํ๏͋Δͷ…ʁʯ
ʮͦͦ PHP ͰϝϞϦͳΜͯؾʹͯ͠ ॻ͍ͨ͜ͱͳ͍Αʯ
ʮPHP ͕ϝϞϦΛѻ͏ΈͳΜͯΒͳ͍Αʯ
Allowed memory size of ... ͳΜͯ͏ා͘ͳ͍… ͱࢥͬͯΒ͑Δͷ͕ ຊͷΰʔϧͰ͢
…ͳͬͯΔͥ…ͷϝϞϦԦʹ!!
ͦͷલʹͳͥϝϞϦ͕Γͳ͘ͳΔͷ͔ ղઆ͍͖ͯ͠·͢
※ PHP 8.3 લఏͰղઆ͠·͢
ϝϞϦͳͥΓͳ͘ͳΔͷ͔
ͦͦϝϞϦͬͯԿʁ - తʹݴͬͯ͠·͑ɼσʔλΛҰ࣌తʹه͢Δͱ͜ΖͰ͢ ʢ※ ࢲͷϋϯυϧωʔϜͱ͕ؔ͋Γ·ͤΜʂʣ - شൃੑϝϞϦʢ͍ΘΏΔ RAMʣෆشൃੑϝϞϦͳͲ͋Γ·͢Ͷɻ - ༻్ʹΑ͚ͬͯΒΕ·͢ɻใܥͷֶ෦ग़ͷਓɼߨٛͰ
ݏʹͳΔ͘Β͍ɼͬͨΜ͡Όͳ͍͔ͳͱࢥ͍·͢ɻ - ओهԱஔͱͯ͠ΘΕΔͷେ͕ RAM Ͱ͢ɻ ϝϞϦͳͥΓͳ͘ͳΔͷ͔
ͦͦϝϞϦͬͯԿʁ - ྫ͑ AWS ͷΠϯελϯεΛબͿͱ͖ʹϝϞϦͷ߲ (r5.large ͳͲ)͕͋Δ ͔ͳͱࢥ͍·͕͢ɼͦΕͰ͢ɻͨͩɼϝϞϦͱݺͿͱ͖Ծ͔ཧ͔͋·Γ ؾʹ͍ͯ͠·ͤΜ -
࣮ࡍଞͷιϑτΣΞͳͲͰϝϞϦΛ༻͍ͯ͠ΔͨΊɼࢦఆͨ͠ϝϞ Ϧ͕શͯ͑ΔͱݶΓ·ͤΜ - ͕ͨͬͯ͠ PHP Ͱ ini_set('memory_limit ', '4G') ͳͲͱ҆ʹ ࢦఆ͢ΔͷϕετϓϥΫςΟεͱݴ͑·ͤΜɻ ϝϞϦͳͥΓͳ͘ͳΔͷ͔
ϝϞϦ֬อͷ͘͠Έ
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - PHP ىಈ࣌ʹ 2M Ҏ্ͷϝϞϦΛͦͦ༻͍ͯ͠·͢ɻ - ྫ͑ɼPHP
ͷ࣮ߦͰ php -d memory_limit=1K -r "" ͱ͢ΔͱɼPHP ͦͷ ͷ͕࣮ߦͰ͖ͳ͍ࣄ͕Θ͔Γ·͢ɻ ϝϞϦ֬อͷ͘͠Έ php -d memory_limit=1K -r ""
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - memory_limit ͷॲཧ https://github.com/php/php-src/blob/php-8.3.2/ main/main.c#L273 ͷ static
PHP_INI_MH(OnChangeMemoryLimit) ͰߦΘ Ε͍ͯ·͢ɻ - ࠷ऴతʹ Zend Memory Manager ͕ݺͼग़͞Εͯɼॲཧ͞Ε͍ͯ·͢ɻ - zend_alloc.c ͷ https://github.com/php/php-src/blob/php-8.3.2/Zend/ zend_alloc.c#L2731 Ͱ͋Δ zend_set_memory_limit Ͱ͢ɻ ϝϞϦ֬อͷ͘͠Έ
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - ./con fi gure --disable-all ͰϏϧυ࣌ʹશͯͷϞδϡʔϧΛແޮԽʹͯ͠ɼ ಛஈϝϞϦ༻ྔ͕ݮΔ͜ͱ͋Γ·ͤΜɻ
- ϞδϡʔϧΛແޮʹͯ͠༗ޮʹͯ͠ɼৗʹ 2,097,152 όΠτ (2M)ɹ͕ফඅ ͞Ε͍ͯΔ͜ͱ͕Θ͔Γ·͢ɻ (Ubuntu 20 on Docker ͷ߹) - ͦΕͳͥͰ͠ΐ͏͔ɻ ϝϞϦ֬อͷ͘͠Έ ./con fi gure --disable-all
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - ԿॲཧΛ͍ͯ͠ͳ͍ͷʹ 2MB Λ༻͍ͯ͠Δཧ༝ zend_alloc_sizes.h ͷ ZEND_MM_CHUNK_SIZE
ͱ͍͏ఆ͕Ωʔͱͳ͓ͬͯΓɼ͜Ε͕ 2MB ͱͳ͍ͬͯΔ͔ΒͰ͢ - ࢀর: https://github.com/php/php-src/blob/php-8.3.2/Zend/ zend_alloc_sizes.h#L22 - PHP ޮΑ͘ॲཧΛ͢ΔͨΊʹɼϝϞϦΛ֬อ͢Δࡍʹ͋ΔఔόοϑΝ Λ࣋ͬͯ֬อ͢ΔͷͰ͢ɻ ϝϞϦ֬อͷ͘͠Έ
ZEND_MM_CHUNK_SIZE ͷఆٛ
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - ZEND_MM_CHUNK_SIZE Λ 4MB ʹมߋ͠ɼPHP ΛϏϧυ͠ͳ͓ͯ͠ىಈ ͯ͠ΈΔͱͲ͏Ͱ͠ΐ͏͔ɻ
- ͦΕʹ߹Θͤͯ memory_limit 3MB ʹม͑ͯΈ·͢ɻ ϝϞϦ֬อͷ͘͠Έ 3MB ʹมߋ 4MB ͍ͬͯΔ͜ͱ͕Θ͔Γ·͢
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - Ͱ memory_limit Λਖ਼ৗʹىಈͰ͖͏ΔͰ͋Ζ͏ 5MB ʹม͑ͯΈ·͢
ϝϞϦ֬อͷ͘͠Έ 5MB ʹมߋ ਖ਼ৗʹग़ྗ͞Ε͍ͯΔ͜ͱ͕ Θ͔Γ·͢ ग़ྗ͞ΕΔ͔Λςετ͢ΔͨΊʹ echo ʹॻ͖͑ͯ·͢
ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ - ZEND_MM_CHUNK_SIZE Zend Memory Manager ʢZend
MMʣͱݺ ΕΔϝϞϦΛཧ͢ΔػߏʹΑͬͯޮతʹϝϞϦΛΞϩέʔτʢAllocateɼ ϝϞϦͷྖҬΛ֬อ͢Δ͜ͱʣͤ͞·͢ɻ - ͜ͷػߏΛແޮʹ͠ɼҰൠతʹϝϞϦͷΞϩέʔτͰ༻͍ΒΕΔ malloc Λ ༻͢Δʹ USE_ZEND_ALLOC=0 ͱ͍͏ڥมΛࢦఆ࣮ͯ͠ߦ͠·͢ɻ ※ PHP ͷϚχϡΞϧʹຊ൪ڥͰͷ༻͠ͳ͍Α͏ॻ͔Ε͍ͯ·͢ɻ ϝϞϦ֬อͷ͘͠Έ
- PHP ͷϝϞϦཧԼͷ֎ʹͳΔͷͰɼmemory_get_usage ͳͲͷΑ͏ͳɼϝ ϞϦؔ࿈ͷ͕ؔɼ΄ͱΜͲಈ࡞͠ͳ͘ͳΓ·͢ɻ ىಈ͚ͩͰ 2M ఔ༻͍ͯ͠Δཧ༝ ϝϞϦ֬อͷ͘͠Έ
USE_ZEND_ALLOC=0 Λࢦఆ͢ΔͱΤϥʔ͕ දࣔ͞Ε࣮ͣߦ͞ΕΔ͜ͱ͕Θ͔Γ·͢ ग़ྗ͞ΕΔ͔Λςετ͢ΔͨΊʹ echo ʹॻ͖͑ͯ·͢
memory_get_usage/memory_get_peak_usage ͷʹ͍ͭͯ - memory_get_usage/memory_get_peak_usage true Λୈ 1 Ҿʹࢦఆ͠ ͨ߹ɼZEND_MM_CHUNK_SIZE
ϕʔεʹͳΓ·͢ɻ - Zend MM ͕ͲΕ΄Ͳ࣮ࡍʹϝϞϦΛ֬อ͍ͯ͠Δͷ͔ΛΓ͍ͨ߹ʹ༗ ༻Ͱ͢ɻ - ͳ͓ɼPHP ͷϓϩηε͕͍ͬͯΔϝϞϦফඅྔͰ͋Γ·ͤΜͷͰҙ ͕ඞཁͰ͢ɻ ϝϞϦ֬อͷ͘͠Έ
memory_get_usage/memory_get_peak_usage ͷʹ͍ͭͯ - ͦͷதͷ௨ৗͷϝϞϦফඅྔΛಘ͍ͨ߹ ୈ 1 Ҿʹಛஈࢦఆ͠ͳ͍΄ ͏͕ྑ͍Ͱ͢ɻ - ୈҰҾΛࢦఆ͠ͳ͍߹ͷϢʔεέʔεͱͯ͠ɼྫ͑ಛఆͷॲཧͷൣ
ғͰͲΕ͘Β͍ϝϞϦ͕ফඅ͞Ε͍ͯΔͷ͔ΛΓ͍ͨਓ͚ʹ༗༻Ͱ͢ɻ - PHP ͷϓϩηεຊମͷϝϞϦ༻ྔͰͳ͍ͨΊ memory_limit ʹϝϞ Ϧͷ༻ྔΛऩΊΔͨΊͷϘτϧωοΫΛ୳͢༻్͘Β͍͔͠ࢲࢥ͍ු͔ ͳ͍Ͱ͕͢…ɻଞʹ͜͏͍͏༻్͕͋ΔΑͳͲ͋Εڭ͍͑ͯͩ͘͞ʂ ϝϞϦ֬อͷ͘͠Έ
memory_get_usage/memory_get_peak_usage ͷʹ͍ͭͯ - ୈ 1 Ҿʹ true Λͨ͠߹ ϝϞϦ֬อͷ͘͠Έ
ʹมԽͳ͠ ʹมԽͳ͠
memory_get_usage/memory_get_peak_usage ͷʹ͍ͭͯ - ୈ 1 Ҿʹ true Λ͞ͳ͔ͬͨ߹ ϝϞϦ֬อͷ͘͠Έ ʹมԽ͋Γ
ʢͨͩ͠෦ͰͷϝϞϦফඅྔมԽͳ͠ʣ ʹมԽ͋Γ ʢͨͩ͠෦ͰͷϝϞϦফඅྔมԽͳ͠ʣ
memory_get_usage/memory_get_peak_usage ͷʹ͍ͭͯ - ͜ΕΒͷ Zend Memory Manager ͕ϕʔεͱͳ͍ͬͯΔͨΊ USE_ZEND_ALLOC=0 ͱͨ͠߹ৗʹ
0 ͕ฦΓ·͢ɻ - ·ͨɼ͜Ε PHP ͕ϓϩηεͱͯ͠༻͍ͯ͠ΔϝϞϦফඅྔͰͳ͍ ʢZend Memory Manager ্Ͱ͋ΔͨΊʣͨΊϓϩηεͦͷͷ͕༻ͯ͠ ͍ΔϝϞϦফඅྔΛΓ͍ͨ߹ɼҟͳΔखஈ͕ඞཁͰ͢ɻ - ) USE_ZEND_ALLOC=0 ɼϝϞϦϦʔΫݕग़࣌Ҏ֎ʹ͏͖ͷͰͳ͍ͱ PHP ϚχϡΞϧʹهࡌ͞Ε͍ͯ·͢ɻ ࢀর: http://php.adamharvey.name/manual/ja/internals2.memory.management.php ϝϞϦ֬อͷ͘͠Έ
memory_get_usage/memory_get_peak_usage ͷʹ͍ͭͯ - PHP ͷϓϩηεͦͷͷ͕ར༻͍ͯ͠ΔϝϞϦ༻ྔΛٻΊ͍ͨ߹ҎԼ ͷΑ͏ʹ͢Δ͜ͱͰऔಘͰ͖·͢ɻ - VSS (Virtual Set
Size, ϓϩηε͕֬อ͍ͯ͠ΔԾϝϞϦͷαΠζ) - system("ps u -p" . getmypid() . " | grep php | awk '{print $5}'"); - RSS (Resident Set Size, ϓϩηε͕༧Ί֬อ͍ͯ͠ΔཧϝϞϦͷαΠζ) - system("ps u -p" . getmypid() . " | grep php | awk '{print $6}'"); ϝϞϦ֬อͷ͘͠Έ system("ps u -p" . getmypid() . " | grep php | awk '{print $5}'"); system("ps u -p" . getmypid() . " | grep php | awk '{print $6}'");
༨ஊ: POST ͷαΠζʹ͍ͭͯ - ଞʹૹΒΕͯ͘Δ POST ͷαΠζΛܾఆ͢Δ post_max_size ͳͲ͕͋Γ· ͢ɻ
- ͜ΕҰ࣌ϑΝΠϧͱͯ͠࡞͞ΕΔͨΊɼmemory_limit > post_max_size Ͱ͋Δඞཁ͋Γ·ͤΜɻ - php -d memory_limit=4M -d post_max_size=16M -S 0.0.0.0:8000 ͰϏϧ τΠϯαʔόʔΛىಈ͠ɼ࣮ࡍʹ 4MB ΑΓେ͖͍ϑΝΠϧΛૹ৴ͯ͠ɼ ͳ͍͜ͱ͕֬ೝͰ͖·͢ɻ ϝϞϦ֬อͷ͘͠Έ
༨ஊ: POST ͷαΠζʹ͍ͭͯ - ͨͩ͠ɼSAPI_POST_BLOCK_SIZE (σϑΥϧτ 16,384 bytes) ͷϝϞϦ ʢZend
Memory Manager ͷ֎Ͱʣ༻͞Ε·͢ɻ - ͜ͷʹ͍ͭͯ memory_get_usage ͳͲͰऔಘͰ͖·ͤΜɻPHP ͷ ෦ґଘͷ࣮ʹͳΓ·͢ɻ - memory_get_usage ɼҰ෦ྫ֎Λআ͖·͕͢ɼجຊతʹϢʔβʔϥϯυ ͷίʔυͷϝϞϦ༻ྔ͕ੵ·Ε͍ͯ͘͜ͱʹҙ͢Δඞཁ͕͋ΔͷͰ͢ɻ ϝϞϦ֬อͷ͘͠Έ
༨ஊ: POST ͷαΠζʹ͍ͭͯ - Λ͢ͱ post_max_size αʔόʔ͕Ұ࣌ϑΝΠϧΛ࡞Ͱ͖Δ༰ྔʹ Αܾͬͯఆ͖͢Ͱ͋Δͱݴ͑·͢ɻ - ొஃ༰͔ΒҳΕΔͷͰৄࡉׂѪ͠·͕͢ɼҰ࣌ϑΝΠϧɼΦʔϓϯՄೳͳ
ϑΝΠϧͳͲΛߟྀͨ͠ͱ͖ʹɼΧʔωϧύϥϝʔλͷௐ͕ඞཁʹͳΔՄ ೳੑ͋Γ͑·͢ɻ ϝϞϦ֬อͷ͘͠Έ
༨ஊ: POST ͷαΠζʹ͍ͭͯ - ͜Ε post_max_size >= upload_max_ fi lesize
Ͱ͋Δඞཁ͕͋Γ·͢ɻ post_max_size ͕શମͷ POST ͷαΠζΛࢦఆ͢Δͷʹରͯ͠ɼ upload_max_ fi lesize POST ͷதͷૹ৴͞Εͨ multipart Λࢀর͢ΔͨΊͰ ͢ɻ - ͳ͓ɼ͜Ε 1 ϑΝΠϧ͋ͨΓͰͳ͘ɼશͯͷϑΝΠϧͷαΠζͷ߹ܭ Ͱ͢ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ - มʹೖΔɼͦͷ··ఆͨ͠ ϝϞϦ༻ྔʹͳΔΘ͚Ͱ͋Γ· ͤΜɻ - ྫ͑ӈهͷίʔυ 0 Λظ͠·
͕͢ɼ࣮ࡍ -256 Ͱग़ྗ͞Ε·͢ɻ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ - $tmp ʹจࣈྻΛೖ͍ͯͯ͠ɼͦ ͷͰ Zend MM ্ͰϝϞϦফඅ ྔՃࢉ͞Ε·ͤΜɻ
- ·ͨɼ$tmp2 PHP CoW (Copy on Write) Ͱ͋ΔͨΊɼಉ༷ʹ ͜ͷ࣌ͰϝϞϦͷফඅྔՃࢉ ͞Ε·ͤΜɻ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ - ͔͠͠ɼӈهͷΑ͏ʹίʔυΛॻ͖͑Δ ͱɼ4,210,712 ͷϝϞϦফඅྔ͕͋Δ͜ͱ͕ Θ͔Γ·͢ - ͭ·ΓɼΘΕ͍ͯͳ͍มͰؔݺͼग़ ͠ͷ߹ϝϞϦফඅ͞ΕΔͱ͍͏͜ͱͰ
͢ɻ - Ώ͑ʹɼͬͯͳ͍ม͕͋Εফ͢ͱ͍͏ ͜ͱΛ৺͕͚·͠ΐ͏ɻ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ - ϓϦϛςΟϒͳΛࢦఆ͢Δ߹ͱɼؔݺͼग़͕͋͠Δ߹Ͱ·ͬͨ͘ ͬͯҧ͏ͱ͍͏͜ͱ͕Θ͔Γ·͢ɻ - ྫ͑͜ΕΛ int ܕ array
ܕͷʹஔ͖͑ͨΒ 0 ͱग़ྗ͞ΕΔ͜ͱ͕Θ͔ Γ·͢ɻͪͳΈʹ memory_get_peak_usage Ͱಉ༷Ͱ͢ɻ - ͭ·Γɼ͋ͨΓ·͑Ͱ͋Γ·͕͢ɼؔݺͼग़͠ۃྗ߇͑ͯɼϓϦϛςΟ ϒܕͰͳΔ͘ॲཧ͢Δ΄͏͕ϝϞϦͱ͍͏؍Ͱޮతͩͱݴ͑·͢ɻ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ - ͱ͍͑ɼϓϦϛςΟϒܕͷϝϞϦফඅྔ ͕θϩ͔ͱ͍͏ͱͦ͏Ͱͳ͍ͷͰ͢ɻ - ઌ΄Ͳͷྫͷؔͷݺͼग़͠Λ͍ͯ͠Δม ఆٛͷՕॴΛྻʹ͢ΔͱͲ͏ͳΔͰ ͠ΐ͏͔ɻ -
͜ΕͰ࣮ߦͯ͠Έ·͠ΐ͏ɻ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ - ϝϞϦফඅྔ 4,210,928 bytes ͱͳΓɼ216 bytes ૿͑Δ͜ͱ͕Θ͔Γ· ͢ɻ
- 2 ࣍ݩྻɼ3 ࣍ݩྻͱ૿͍ͯ͘͠ͱɼϝϞϦফඅྔ͕૿͍͖͑ͯ·͢ - ྻʹ͢Δ͚ͩͰ༻ྔ͕มΘΔͱ͍͏͜ͱ͕Θ͔Γ·͢ɻ - จࣈྻܕྻܕͳͲ͕Ͳͷ͘Β͍ϝϞϦΛ͏͔ʹ͍ͭͯ zend_types.h ʹهࡌ͞Ε͍ͯ·͢ ϝϞϦ֬อͷ͘͠Έ
PHP ͷϝϞϦͱมͷؔ จࣈྻܕྻܕͳͲ͕Ͳͷ͘Β͍ϝϞϦ Λ͏͔ʹ͍ͭͯ zend_types.h ʹهࡌ ͞Ε͍ͯ·͢ɻͳ͓ɼܕͷ߹ zend_long.h Ͱఆٛ͞Ε͍ͯ·͢ɻ
ϝϞϦ֬อͷ͘͠Έ จࣈྻͷ߹ ྻͷ߹
PHP ͷϝϞϦͱมͷؔ ϝϞϦ֬อͷ͘͠Έ - ·ͨɼint ܕ string ܕͩͬͨΒৗʹ
0 ͔ͱ ͍͏ͱɼͦ͏͍͏Θ͚Ͱ͋Γ·ͤΜɻ - ӈਤͷΑ͏ʹจࣈྻΛ 3MB ॻ͖ग़ͨ͠ ϑΝΠϧΛ࡞͠ɼ࣮ࡍʹ࣮ߦ͢Δͱ ҎԼͷΑ͏ʹΤϥʔ͕ग़·͢
GC ͱ ऑࢀরʢWeakrefʣ ($ (BSCBHF$PMMFDUJPO ΨϕʔδίϨΫγϣϯ ɼҰఆͷ݅Λຬͨͨ͠ ߹ʹɼมͷϝϞϦղ์Λߦ͏ͷͰ͢
1)1ʹSFGDPVOUʢϦϑΝϨϯεΧϯτʣͱݺΕΔɼ͍Θมͷݺͼ ग़͠ճΛه͢Δػೳ͕͋Γɼ͜ͷΛ༻͍ͯɼ($ͷରͰ͋Δ͔Ͳ͏͔ Λఆ͍ͯ͠·͢ ࢀরIUUQTXXXQIQOFUNBOVBMKBGFBUVSFTHDSFGDPVOUJOH CBTJDTQIQ ϝϞϦ֬อͷ͘͠Έ
GC ͱ ऑࢀরʢWeakrefʣ ಛʹʹͳΓ͍͢ͷ॥ࢀরͰ͢ɻ॥ࢀরͱɼ"ͱ#ͷΦϒδΣΫ τม͕͋ͬͨͱ͖ʹɼ"͕#Λɼ#͕"Λࢀরʢ˺ґଘʣ͢Δঢ়ଶΛࢦ ͠ɼϝϞϦ͕֬อ͞Εͨ··ʹͳΓɼ࠷ऴతʹϝϞϦϦʔΫͱͳͬͯ͠·͏ ͷͰ͢ɻ ॥ࢀর͕ൃੜ͢Δͱ($͕Δ·ͰɼϝϞϦ͕ফඅ͞Εͯ͠·͍·͢ɻ
͕ͨͬͯ͠ɼͦͦ॥ࢀরʹͳΒͳ͍Α͏ͳΞʔΩςΫνϟΛ ਪ͠·͢ ϝϞϦ֬อͷ͘͠Έ
॥ࢀরΛൃੜͤ͞Δίʔυͷྫ
GC ͱ ऑࢀরʢWeakrefʣ ॥ࢀরͰɼ($͕Βͳ͔ͬͨ߹ɼҎԼͷΑ͏ʹ"MMPXFENFNPSZTJ[F PG͕ग़ྗ͞Ε·͢ɻ ϝϞϦ֬อͷ͘͠Έ
GC ΛखಈͰൃಈͤ͞Δྫ echo $cycle2; ͷਅԼʹ gc_collect_cycles(); Λه
GC ͱ ऑࢀরʢWeakrefʣ ҰํͰखಈͰHD@DPMMFDU@DZDMFTΛ࣮ ߦʢFDIPDZDMFਅԼʹՃʣͨ͠ ߹ɼӈهͷΑ͏ʹ࠷ޙ·Ͱɼϓϩά ϥϜ͕࣮ߦ͞ΕΔ͜ͱ͕Θ͔Γ·͢ɻ ϝϞϦ֬อͷ͘͠Έ
GC ͱ ऑࢀরʢWeakrefʣ ॥ࢀরʹΑͬͯɼSFGDPVOU͕૿͍͑ͯͨ͘Ίɼ($ΛखಈͰൃಈ͠ͳ͍ͱϝ ϞϦղ์͕ߦΘΕͳ͍͜ͱ͕Θ͔Γ·ͨ͠ɻ ͱ͍͑ɼ1)1্ͰҙͷλΠϛϯάͰ($ΛΒͤΔͷਓྨʹ·ͩૣ ͍ͨΊɼऑࢀরʢ8FBL3FGʣΛ༻͢ΔͳͲͷ͕ඞཁͰ͢ɻ
ઌ΄ͲͷίʔυྫΛऑࢀর͕͑ΔΑ͏ʹॻ͖͑ɼղઆ͍͖ͯ͠·͢ɻ ϝϞϦ֬อͷ͘͠Έ
CycleTest Λऑࢀরʹͤ͞Δ ऑࢀরͷΦϒδΣΫτΛ CycleTest ʹ͢ ड͚ೖΕΔܕΛม͑Δ ड͚ೖΕΔܕΛม͑Δ
GC ͱ ऑࢀরʢWeakrefʣ ऑࢀরʹॻ͖͑ͨ͜ͱͰɼSFGDPVOU͕͍ ͍ײ͡ʹௐઅ͞Ε͏·͘($͕ΔΑ͏ʹ ͳΓ·ͨ͠ɻ݁Ռͱͯ͠࠷ޙ·Ͱϓϩάϥ Ϝ͕࣮ߦͰ͖ΔΑ͏ʹͳ͍ͬͯ·͢ɻ ·ͨɼಠཱͨ͠ΦϒδΣΫτΛ͏͜ͱͰ
ճආ͢Δ͜ͱͰ͖·͢ɻ͜ͷΑ͏ͳέʔ εͷ߹DMPOFΛ༻͍Δ͜ͱ͕༗༻Ͱ͢ɻ ϝϞϦ֬อͷ͘͠Έ
clone Λ͏ͱ॥ࢀরͰͳ͘ͳΔͨΊ memory_limit ͕ 2M Ͱ࠷ޙ·Ͱग़ྗͰ͖Δ
ϝϞϦফඅྔΛݮ͢Δʹ
memory_limit ͷϕετϓϥΫςΟε - 2*N ʢN ࣗવʣMB Λߟྀͯ͠ memory_limit ઃఆΛ͠·͠ΐ͏ɻ -
ͦͦ memory_limit ͷԼݶ 2MB (ZEND_MM_CHUNK_SIZE ʹΑΔ)ͳ ͷͰɼϝϞϦফඅྔ 2MB ҎͰॲཧ͕ॻ͚Δͱϕετ - ͜Ε memory_limit ͷσϑΥϧτ 128MB Ͱ͋ͬͯɼॳճͷղ์͞ΕΔ ͕ 2MB ͱ͍͏͜ͱͰ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
memory_limit ͷϕετϓϥΫςΟε - 2MB+1B ͔ͬͯ͠ͳ͍Α͏ʹݟ͑ͯɼཪͰ݁ہ 2MB (ZEND_MM_CHUNK_SIZE) * 2 =
4MB ϝϞϦΛফඅͯ͠ΔΘ͚Ͱ͢ɻ - memory_get_usage(false) ͳͲͷΛνϚνϚվળͯ͠ɼ݁ہϝϞϦ ফඅ͞Ε͍ͯΔͷͰҙຯ͕͋Γ·ͤΜɻ࣌ؒΛ͏͚ͩແବͰ͢ɻ - ͜ͷΑ͏ͳέʔε 4MB ϑϧʹͬͨ΄͏͕ޮతͰ͢ɻ - ͭ·ΓɼPHP ʹ͓͚Δ memory_limit 2MB ͷഒΛઃఆ͠ɼͦͷ ͷதͰͬͯ͋͛Δͷ͕࠷ޮతͰޮՌతͰ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
memory_limit ͷϕετϓϥΫςΟε - ྫ͑ AWS Λ༻͍ͯ͠ΔํͰ c5.large Λબఆ͍ͯ͠Δ߹ϝϞϦ 4GB ͱͳΔͷͰɼphp-fpm
ͳͲͷଞϓϩηεͷϝϞϦ༻ྔՃຯ্ͨ͠Ͱ - 2M * N (1 <= N < (4G/2), N ࣗવ) ͳͲͱݟੵΔͱྑ͍Ͱ͠ΐ͏ɻ - ࡢࠓͷΞϓϦέʔγϣϯΨϕʔδίϨΫγϣϯʹ͖ͤΓͰɼϝϞϦϦʔΫ Λසൟʹى͍ͯͨ͜͠Γ͠·͢ɻΏ͑ʹɼطଘͷΞϓϦέʔγϣϯͷঢ়ଶ ͪΖΜՃຯ͢Δ͜ͱ͕ॏཁͰ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
memory_limit ΑΓେ͖ͳΛ͍͍ͨ - εϫοϓόοϑΝΛ͏·͘ѻ͏͜ͱͰɼmemory_limit ΑΓେ͖ͳΛ ͏͜ͱ͕ՄೳͰ͢ɻ - ྫ͑ memory_limit Λ
2M ͱࢦఆ͍ͯ͠Δ߹Ծఆ͠·͢ɻ͜ͷέʔεͷ ͱ͖ɼ 4M ͷϑΝΠϧͷதΛग़ྗ͠Α͏ͱ `echo fi le_get_contents('test_heavy.log')` ͷΑ͏ʹ۪ʹॻ͘ͱϝϞϦ͕ෆ ͯ͠͠·͍·͢ɻ - ࣍ͷϖʔδͷΑ͏ʹׂͯ͋͛͠Δ͜ͱͰϝϞϦফඅྔΛ͑Δ͜ͱ͕ՄೳͰ ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ echo fi le_get_contents('test_heavy.log')
ͪͳΈʹɼ͋ͨΓ·͑Ͱ͕͢ fread ͷୈೋҾΛ 2M ʹมߋ͢ΔͱϝϞϦෆʹͳΓ·͢
memory_limit ΑΓେ͖ͳΛ͍͍ͨ - PHP Λհͯ͠ը૾Λ base64 ͱͯ͠ग़ྗ͍ͨ͠έʔεͳͲ͋Δ͔ͱࢥ͍· ͢ɻ - ϑΝΠϧαΠζ͕খ͍͞ɼ͘͠ఆ·͍ͬͯΔͷͳΒɼ·ͩڐ༰Ͱ͖·͢
͕ɼϑΝΠϧαΠζ͕େ͖͍߹Ұ͕ඞཁͰ͢ɻ - ಛʹ PHP ͕ϏϧτΠϯͰఏڙ͍ͯ͠Δbase64_encode/base64_decode શ ͯͷจࣈྻΛ͢ඞཁ͕͋Γ·͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
memory_limit ΑΓେ͖ͳΛ͍͍ͨ - 57 * 143 bytes ͝ͱʹׂͨ͠จࣈྻΛ base64_encode ͢Δ͜ͱ͕࣮Մೳ
Ͱ͢ɻ͜Ε base64 ΤϯίʔσΟϯάͷΈʹଇͬͨͪΐͬͱٕͨ͠Ͱ ͢ɻ - ࢀর: https://www.php.net/manual/ja/function.base64- encode.php#111942 - ຊ͜ΜͳখखઌͷٕΛ͏ͷͰͳ͘ɼCDN ʹஔ͘ͳͲΞʔΩςΫνϟ ͱͯ͋͠Δ͖࢟ࢦ͍͖͍ͯͨ͠ͷͰ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
ׂͰग़ྗ͢Δ͜ͱͰɼmemory_limit ͕ 2M Ͱਖ਼͘͠දࣔͰ͖·͢
ob_* ؔͷέʔε ଞʹPC@TUBSUPC@HFU@DMFBOΛ͏ͳͲ ͕͋Γ·͢Ͷɻ࣮PC@TUBSUͷୈҾʹ όοϑΝΛड͚औΓɼͦͷΛՃ͢Δ͜ͱ ͕Ͱ͖ΔίʔϧόοΫΛ͢͜ͱ͕Ͱ͖· ͢ɻ ͜ͷίʔϧόοΫΛ׆༻͠ɼࢦఆͨ͠νϟϯ
ΫαΠζͷΛग़ྗ͢ΔͳͲͯ͠ผϑΝΠϧ ʹॻ͖ࠐΉͳͲͰϝϞϦফඅྔΛ͑ΒΕ· ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠