像java、nodejs,應該都是在服務端持續啟動並執行一個程式,這個程式會一直運行,會佔用cpu,會佔用記憶體,接到網路請求,就會處理。
而PHP似乎不是一個程式,更類似於html,只有開啟的時候才會執行,當沒有人訪問php的服務時,php甚至一點點記憶體都不佔,一點點cpu都不佔,是這樣嗎?
如果是這樣,那php不是很難封裝資料庫class?因為每個使用者進來都要給他開一個進程,進程之間互不相通,A使用者進來給他開一個資料庫連接,B使用者進來又要給他單獨開資料庫連接。那php不是在不斷串連和斷開資料庫?使用者多了之後,開銷應該很大吧?
這也是導致php沒有類似js的 setInterval 或者 setTimeout 函數的原因嗎?
回複內容:
像java、nodejs,應該都是在服務端持續啟動並執行一個程式,這個程式會一直運行,會佔用cpu,會佔用記憶體,接到網路請求,就會處理。
而PHP似乎不是一個程式,更類似於html,只有開啟的時候才會執行,當沒有人訪問php的服務時,php甚至一點點記憶體都不佔,一點點cpu都不佔,是這樣嗎?
如果是這樣,那php不是很難封裝資料庫class?因為每個使用者進來都要給他開一個進程,進程之間互不相通,A使用者進來給他開一個資料庫連接,B使用者進來又要給他單獨開資料庫連接。那php不是在不斷串連和斷開資料庫?使用者多了之後,開銷應該很大吧?
這也是導致php沒有類似js的 setInterval 或者 setTimeout 函數的原因嗎?
以PHP-FPM為例(類似Apache MOD_PHP)說說PHP的運行機制.
首先,PHP-FPM是一個C實現的多進程FastCGI服務.
每個PHP-FPM背景工作處理序都內建了PHP解譯器,不依賴PHP-CGI,都支援後台常駐,比如配置:
nginx.conf: 訪問io.php的請求都交給監聽9001的PHP-FPM進程池處理location = /io.php { include fastcgi_params; fastcgi_pass 127.0.0.1:9001; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;}php-fpm: 正常指令碼由靜態www池處理,阻塞指令碼由動態io池處理[www];名為www的進程池監聽9000連接埠,常駐進程數量為固定4個listen = 127.0.0.1:9000pm = staticpm.max_children = 4[io];名為io的進程池監聽9001連接埠,進程數常駐4個,最大8個listen = 127.0.0.1:9001pm = dynamicpm.max_children = 8pm.start_servers = 4pm.min_spare_servers = 4pm.max_spare_servers = 4
PHP-FPM主進程就是用來管理這些背景工作處理序的,比如一個背景工作處理序被殺死了,立馬重建一個.
PHP-FPM提供給了pm.status_path來通過瀏覽器查看整套PHP-FPM服務的工作狀態.
像執行逾時放棄,處理指定請求數後自動重啟背景工作處理序,慢日誌記錄(找出耗時的檔案和函數)都支援.
而且開啟持久串連後,每個PHP-FPM背景工作處理序都能保持一個到MySQL的長串連不釋放,避免重複串連資料庫.
比如展示的是2個PHP-FPM進程跟MySQL建立的2個長串連:
另外,針對Memcached和Redis的PECL擴充也都實現了持久串連的功能.
上面說了PHP-FPM的體系,下面就該說說PHP指令碼在PHP-FPM體系下的生命週期.
PHP指令碼裡的量(包括全域變數)的生命週期只存在於一次請求內,請求處理完成,PHP-FPM就自動釋放資源.
一次請求釋放一次資源,這種記憶體釋放是非常徹底的,PHP基於引用計數的GC甚至都還沒發揮作用程式就已經結束了.
這裡的釋放資源指的是指令碼裡控制的資源,而不會幹預到PHP-FPM常駐進程,不會讓PHP-FPM進程關閉,也不能讓PHP-FPM關閉到MySQL的持久串連,PHP-FPM只負責輸入PHP指令碼,執行PHP操作,如果加入了ZendOpcache支援,還可以把解析PHP指令碼產生的opcode全部緩衝到記憶體裡共下次直接解釋執行.PHP7中還支援用opcache.file_cache匯出指令碼opcode實現原始碼保護.
PHP的一些常識:
資料庫連接池: PHP持久串連就是天然的透明的無需程式幹預的串連池,支援MySQL/Memcached/Redis等.
記憶體駐留: PHP-FPM進程,ZendOpcache緩衝的指令碼的opcode,鳥哥開發的Yac都是記憶體駐留的.
記憶體回收: PHP-FPM一次請求釋放一次資源的運行模式,削弱了基於引用計數的GC的作用.
最後,CLI下工作的PHP守護進程服務比如Swoole/WorkerMan才跟Java/Node之類相似.
雖然我已經下班了,看到你這個提說PHP是類似html我忍不了。PHP功能是html無法比擬的好不好,就拿你說的串連資料庫的例子來說,html能串連資料嗎?能讀取資料庫內容嗎?不能吧!還有你說多個使用者來訪問每個使用者都要開一個資料庫連接,你這樣太小看PHP了。封裝一個資料庫連接類很簡單很簡單,這些我就不貼code了。PHP手冊每種資料庫擴充都有介紹也有案例,你可以自己做參考。你既然提到java那肯定也知道單例模式吧!PHP封裝好一個資料庫連接類設定單例模式就可以實現資料連線靜態化。不管多少使用者來訪問直接調用一下就可以不是你說的多個使用者來訪問就開多個進程。還有你提到的setInterval和setTimeout不就是定時執行嗎!PHP也可以的啊!首先定義好PHP要實現的功能,然後通過在伺服器上設定crontab就可以了,參數自己設定就行,或者還有php-fpm。還有等等等的功能我就不羅列了,也沒整理答案格式你先湊活著看。我得下班走人了,有問題咱明天繼續討論
總之,PHP是一門很好很好的語言,功能很強大……而且還在不斷的發展壯大中……易學易懂啊!兄弟
PHP不能常駐記憶體,每一個HTTP請求開後,串連資料庫,等請求結束了,資料庫連接 和 各種變數都釋放掉了。
你總體上的理解是對的,但的不是所有的語言都是java那種常駐記憶體的,python,go,c都不是。PHP也確實沒有連結池的概念,進程執行完就好釋放掉,不會留著給其他進程用
給你 《深入理解 PHP 核心》第二章第一節的內容連結:
http://www.php-internals.com/...
你的疑惑,只是因為你只看到了表面。
如果你用過 swoole,我想你肯定不會提出這種問題。
呃,你當php-fpm沒到。。。
而PHP似乎不是一個程式,更類似於html
PHP只是可以嵌入到HTML中,但跟HTML是天壤之別,PHP有很多擴充可以做不同的事情,HTML能嗎?
只有開啟的時候才會執行,當沒有人訪問php的服務時,php甚至一點點記憶體都不佔,一點點cpu都不佔,是這樣嗎?
PHP主要有兩種運行方式(除了CLI):
1.Apache為代表的mod_php,這時工作是交給Apache處理了。
2.Nginx/Lighttpd用的php-fpm(fastcgi進程管理器),這個是常駐的守護進程。
所以說,怎麼可能不佔CPU和記憶體?
如果是這樣,那php不是很難封裝資料庫class?因為每個使用者進來都要給他開一個進程,進程之間互不相通,A使用者進來給他開一個資料庫連接,B使用者進來又要給他單獨開資料庫連接。那php不是在不斷串連和斷開資料庫?使用者多了之後,開銷應該很大吧?
以MySQL為例,如果串連時選擇pconnect(持久串連)的話,下次就會直接使用已存在的串連,不會關閉串連。
PDO也有長串連選項。
這也是導致php沒有類似js的setInterval或者setTimeout函數的原因嗎?
PHP是有延時函數(如sleep())的哦,而且精度比JS的高太多太多了(微秒層級)。
好熱鬧啊。 @ivanilla 的回答與評論包含好多資訊,感謝。
其實我認為針對樓主的問題,PHP的運行機制就是解釋執行指令碼。PHP是為中小型網站提供服務端支援的指令碼語言,在開發速度與運行效率上具有良好的平衡,這是它成功的原因。
所以樓主的其它觀點就沒啥看頭了,連爭論都無意義,如果PHP擁有了你想像的那些東西,這個語言也就沒人用了,大家乾脆還是用java好了。
樓主對PHP的一些基礎知識不瞭解,應該是剛開始接觸PHP。簡單來說PHP可以以兩種模式運行,一種是指令碼方式,如在 shell 裡執行 php xxx.php;一種是樓主理解的有網路請求才啟動運行(不是十分貼切),有編譯成apache的擴充方式,也有fast-cgi方式。apache的mod_php方式就是來一個請求起一個進程執行,效率底下,相應的有各種參數最佳化等。而fast-cgi則要高效得多,具體的樓主可以翻看相應的手冊並實際操作一下。
樓上幾位真有耐心