鍍金池/ 問答/PHP  Python/ python為何效率慢點?PHP跟Python的解釋器都是C寫的,PHP為什么能

python為何效率慢點?PHP跟Python的解釋器都是C寫的,PHP為什么能快點?

其實用python的人應(yīng)該都是不關(guān)注它性能的人,畢竟寫python確實很愉快
PHP的核心維護(hù)者花了很多的心血卻提高底層的解釋器效率,為什么Python的維護(hù)者不去呢?


程序員都喜歡用數(shù)據(jù)說話,這里我用的python版本是Python 3.6.2(64位),php版本是PHP 7.0.12(64位),node版本是v6.11.0(64位),Go 1.8.3(64位),C# 基于.Net 4.0,lua 5.1.4

對比

python

import time

calNum = 100000000

def test():
    sum = 0
    for x in range(1, calNum + 1):
        sum += x
    return sum


start = time.time()

test()

end = time.time()

print(end - start)

PHP

<?php

$calNum = 200000000;

function test() {
    $sum = 0;
    global $calNum;
    for ($i = 0; $i < $calNum; $i++) { 
        $sum += $i;
    }
    return $sum;
}

$start = time();

test();

$end = time();

echo ($end - $start);

nodeJS


let calNum = 200000000;

function test() {
    let sum = 0;
    for (var i = 0; i < calNum; i++) {
        sum += i;
    }
    return sum;
}

let start =  new Date().getTime();

test();

let end =  new Date().getTime();

console.log((end - start) / 1000);

Golang

package main

import (
    "fmt"
    "math"
    "time"
)

var calNum = 200000000

func test() int {
    sum := 0
    for i := 0; i < calNum; i++ {
        sum += i
    }
    return sum
}

func main() {
    start := time.Now().UnixNano()
    test()
    end := time.Now().UnixNano()
    fmt.Println(float64(end - start) / math.Pow(10, 9))
}

C#

 private static int calNum = 100000000;

        static int test()
        {
            int sum = 0;
            for (int i = 0; i < calNum; i++)
            {
                sum += i;
            }
            return sum;
        }

        static void Main(string[] args)
        {
            double start = ConvertDateTimeInt(DateTime.Now);
            test();
            double end = ConvertDateTimeInt(DateTime.Now);
            Console.WriteLine(end - start);
            Console.ReadLine();
        }

        /// <summary>
        /// DateTime時間格式轉(zhuǎn)換為Unix時間戳格式
        /// </summary>
        /// <param name="time"> DateTime時間格式</param>
        /// <returns>Unix時間戳格式</returns>
        public static double ConvertDateTimeInt(DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (time - startTime).TotalSeconds;
        }

lua

calNum = 200000000


function test()
    local sum = 0
    for i=0,calNum - 1 do
        sum = i + sum
    end
    return sum
end

local start = os.time()
test()
local endTime = os.time()

print(endTime - start)

執(zhí)行時間(1億次,2億次)

python

C:\Users\mh\Desktop>python cal.py
7.873001337051392

C:\Users\mh\Desktop>python cal.py
17.40298104286194

PHP

C:\Users\mh\Desktop>php cal.php
5
C:\Users\mh\Desktop>php cal.php
13

PHP 7.1(新下載的)

C:\Users\mh\Desktop>php cal.php
5
C:\Users\mh\Desktop>php cal.php
10

nodeJS

C:\Users\mh\Desktop>node cal.js
1.288

C:\Users\mh\Desktop>node cal.js
2.603

Golang

C:\Users\mh\Desktop>go run cal.go
0.0519903

C:\Users\mh\Desktop>go run cal.go
0.1080017

C#

0.685999155044556

1.52999567985535

lua(just for fun)

C:\Users\mh\Desktop>cal.lua
1

C:\Users\mh\Desktop>cal.lua
2

PHP還是比python快的,不過在腳本語言中node更快,Go挺快的

回答
編輯回答
糖豆豆

PHP的核心維護(hù)者花了很多的心血卻提高底層的解釋器效率,為什么Python的維護(hù)者不去呢?

可能是因為 php 以前太慢了唄。

2018年8月7日 12:17
編輯回答
款爺

python并不一定慢,許多Python的科學(xué)計算庫通過用C來編寫可以獲得和全用c或者c++寫的程序相同或者慢一到兩倍的體驗。

很多人認(rèn)為他慢。他其實也確實慢。
一是GIL,其實GIL也只是CPython python解釋器的特性,其主要是在多核機器上python無法獲得多核所帶來的性能優(yōu)勢。單核其實就差不多了。
樓下起風(fēng)了不認(rèn)可。首先大多數(shù)Python程序都是運行在CPython上的。無數(shù)用c語言為Python編寫的好的庫也是只能運行在cpyhon上的。所以GIL是大多數(shù)Python程序繞不開的東西。你說多進(jìn)程可以解決。但是這也導(dǎo)致了一個問題就是進(jìn)程間的數(shù)據(jù)共享問題。因為不在一個進(jìn)程中共享內(nèi)存空間這種高效的共享方式不能使用(當(dāng)然GIL也是為了處理多線程共享內(nèi)存所帶來的風(fēng)險而設(shè)置的。)這樣你多線程間通信也會帶來性能的損耗。當(dāng)然你說可以通過多線程解決也沒錯,但是也不能說GIL不是導(dǎo)致大多數(shù)python慢的原因。

二是python是一門解釋形語言,其是邊運行邊將python字節(jié)碼編譯成系統(tǒng)可以執(zhí)行的可執(zhí)行代碼。這會帶來一定的性能損耗,但是一個程序的快慢主要還是由其熱點部分決定。通過將熱點部分使用C語言編寫,基本就可以獲得很好的性能。
樓下起風(fēng)了說python運行一次后編碼就完成了。我想他可能沒有理解解釋型語言的編譯。 Python在運行前編譯好的文件是Python字節(jié)碼。如果沒有Python虛擬機是不能運行的。當(dāng)在運行的時候Python虛擬機又吧Python字節(jié)碼翻譯成可以被CPU執(zhí)行的二進(jìn)制字節(jié)碼。而像C語言這種是直接編譯連接就可以生成直接被機器執(zhí)行的二進(jìn)制碼。

其實對于大型應(yīng)用影響其性能的首先是架構(gòu)其次是程序編寫邏輯然后是語言特性。大部分系統(tǒng)瓶頸都輸數(shù)據(jù)庫讀取。加個redis緩存就可以獲得不錯的性能提升。 ins還不是用django撐起了全球最大圖片分享網(wǎng)站。
手機打的錯別字可能多一點??

import time

calNum = 100000000

def test():
    sum = 0
    for x in range(1, calNum + 1):
        sum += x
    return sum

def test1():
    sum = 0
    for x in xrange(1, calNum + 1):
        sum += x
    return sum

def test2(mylist):
    sum = 0
    for x in mylist:
        sum += x
    return sum

def test3():
    sum = 0
    i = 0
    while i < calNum:
        sum += i
        i += 1
    return sum

start = time.time()
test()
end = time.time()
print 'test time: {0}'.format(str(end-start))

start = time.time()
test1()
end = time.time()
print 'test1 time: {0}'.format(str(end-start))

mylist = range(1, calNum + 1)
start = time.time()
test2(mylist)
end = time.time()
print 'test2 time: {0}'.format(str(end-start))

start = time.time()
test3()
end = time.time()
print 'test3 time: {0}'.format(str(end-start))

四種不同的寫法
test time: 7.10620498657
test1 time: 4.30882191658
test2 time: 4.70718193054
test3 time: 8.60779190063

四種不同的寫法 獲得時間也不同。 我之后再寫一個鏈接了c語言庫的實例補上。

2018年8月21日 23:26
編輯回答
墨小羽

不清楚樓主說的效率是指哪方面的效率?

樓主有做過對比測試嗎?

python3.6開始已經(jīng)開始針對GIL的問題進(jìn)行解決了,并準(zhǔn)備摒棄這個東西了??梢允媚恳源?。

2018年8月3日 11:49
編輯回答
情已空

我對樓上的解釋持懷疑態(tài)度。如果你覺得GIL是導(dǎo)致慢的原因,大可以用多進(jìn)程替代,GIL的問題本質(zhì)是導(dǎo)致多線程是分時復(fù)用而已(如果一個線程不間斷地在 Python 2 中運行 1000 字節(jié)碼指令,或者不間斷地在 Python 3 運行15 毫秒,那么它便會放棄 GIL,而其他線程可以運行)。而且由于GIL本身,甚至可以導(dǎo)致多線程比單線程還慢。而且GIL是CPython的,大可用別的版本的Python實現(xiàn)。再者,并不是每個程序都有必要通過多線程去實現(xiàn),而且事實上大多數(shù)人寫的程序就是單線程的,所以這不能成為你的Python程序慢的借口。

Python說到底是一門高級語言,高級語言比低級語言慢是很正常的事情,你去看看leetcode里面解題時間vs不同語言的柱狀圖就知道差距了,反正不是樓上說的一兩倍。再說上面提到的邊運行邊編譯字節(jié)碼的問題,除了主腳本以外,如果別的py文件沒做改動,且運行的python解釋器版本相同,它是不會重新編譯的,而且python添加了編譯優(yōu)化選項,所以我覺得這也不是個很好的理由。比如你寫了一個for循環(huán),循環(huán)上萬次,里面就只是數(shù)據(jù)結(jié)構(gòu)動態(tài)重綁定之類的簡單操作或者就是簡單的加法(沒有類型的加法),那你能說是編譯,加載,連接是主要導(dǎo)致慢的原因嘛?再說很多比Python快的面向?qū)ο蟮恼Z言也會用到虛擬機,總不能一股腦全部賴在這個中間步驟上。

至于為什么慢,又回到高級語言的話題上,python是1.高級的 2.動態(tài)的,戳這里
樓上提到主要解決熱點問題是一致推薦的,一般prototype用python編寫,較慢的代碼會用低級語言重構(gòu)。

當(dāng)我們一定要討論某種語言快慢的時候,是不是應(yīng)該剖析語言本身的特性和準(zhǔn)則,而并不是針對某個特定實現(xiàn)版本,雖然即使這個版本是大多數(shù)人用的。

只是本人基于自己的理解YY的,大家討論哈~

2017年11月4日 19:04
編輯回答
紓惘

看到其他答案都在為Python性能擔(dān)憂,我這邊也提供一個對性能提升的方法,題目的Python代碼幾乎不用變,只要加個 jit 修飾器即可,性能可秒殺其他語言,并且規(guī)模越大優(yōu)勢越明顯:

import time
from numba import jit
calNum = 300000000

@jit
def test():
    sum = 0
    for x in range(1, calNum + 1):
        sum += x
    return sum


start = time.time()

test()

end = time.time()

print(end - start)

數(shù)字直接飆到3億,運行一下看看,你一定會回來贊我的。

這個模塊可以在 https://www.lfd.uci.edu/~gohl... 下載。

2017年4月22日 16:40
編輯回答
涼汐

韓天峰大大寫到:

benchmarksgame 上面的測試基本上都是密集計算的。PHP 和 Python(CPython) 目前都沒有 JIT,PHP
能勝出只能說明底層 VM 性能比 Python 的要好。實際上 PHP 語言官方開發(fā)組從 5.4 時代就一直在優(yōu)化 VM 的性能。PHP7版本對底層的數(shù)據(jù)結(jié)構(gòu)進(jìn)行了很大的改造,相比 5.6 提升了 1 倍以上的性能。而 Python 3 相比 Python 2性能上反而是在退步。 密集計算場景,靜態(tài)語言和 有 JIT 的動態(tài)語言 會有很大的優(yōu)勢??梢钥吹?Node.js(基于 V8 引擎)的測試成績遠(yuǎn)超 PHP 和 Python 。前者的計算指令是直接作為 CPU 指令執(zhí)行的,后者計算實際上是 VM
上的高級指令,實現(xiàn)原理上有很大差異。不過,各位 PHPer 也別灰心,PHP 官方開發(fā)組已經(jīng)在開發(fā) JIT 特性了,也許下個版本 PHP就會攜帶 JIT ,到時在密集計算場景下將會和 Node.js 在同一數(shù)量級。另外再說句,PHP、Python、Node.js都是寫應(yīng)用軟件的,語言的計算性能沒那么重要。你的程序如果對性能敏感,C/C++/GO/Rust 這些靜態(tài)編程語言才是最好的選擇。

同為動態(tài)語言,python的性能為何只有PHP的五分之一?

2017年2月20日 21:20