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
事業観点から見る技術的負債の返済
memory1994
PRO
4
860
PHP でアセンブリ言語のように書く技術
memory1994
PRO
1
180
PHP でアセンブリっぽく書く技術
memory1994
PRO
1
110
How to implement a RubyVM with PHP?
memory1994
PRO
3
2.4k
二郎系ラーメンのコールで学ぶ AST 解析
memory1994
PRO
8
2.5k
RubyVM を PHP で実装する 〜Hello World を出力するまで〜
memory1994
PRO
1
750
技術的負債が生まれる背景を理解して,アーリーからレイター向けの根本的なアプローチを考える
memory1994
PRO
23
9k
激辛のすゝめ
memory1994
PRO
1
560
RubyVM を PHP で実装する 〜Hello World を出力するまで〜
memory1994
PRO
1
6.3k
Featured
See All Featured
Why Our Code Smells
bkeepers
PRO
335
57k
Six Lessons from altMBA
skipperchong
27
3.5k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
1
160
GitHub's CSS Performance
jonrohan
1030
460k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
Building an army of robots
kneath
302
44k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
800
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
0
90
Being A Developer After 40
akosma
87
590k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
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ͷୈҾʹ όοϑΝΛड͚औΓɼͦͷΛՃ͢Δ͜ͱ ͕Ͱ͖ΔίʔϧόοΫΛ͢͜ͱ͕Ͱ͖· ͢ɻ ͜ͷίʔϧόοΫΛ׆༻͠ɼࢦఆͨ͠νϟϯ
ΫαΠζͷΛग़ྗ͢ΔͳͲͯ͠ผϑΝΠϧ ʹॻ͖ࠐΉͳͲͰϝϞϦফඅྔΛ͑ΒΕ· ͢ɻ ϝϞϦফඅྔΛݮ͢Δʹ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠