標籤:機制 模式 方案 工廠 function tno 需要 ios value
V8是Google開源的一個高效能JavaScript引擎,用 C++ 實現,並用在Google的開源瀏覽器Chrome裡。
為什麼V8非常快,哪種方案讓V8達到這種速度?發現其中秘密是一件有趣的事情。
物件導向、設計模式與效能
有些C/C++開發人員有些奇怪的觀念。他們認為使用物件導向和設計模式會降低程式的效能。但V8證明了這種觀念是錯誤的。V8的實現使用了許多設計模式,但依然非常高效。
下面列出V8中使用的兩個模式:
原廠模式
當Javascript引擎執行一個指令碼時,引擎為遇到的每個變數、函數或數組都建立一個執行個體。JSObject是所有這些對象的父物件。
下面列出了所有繼承自JSObject的類:
V8實現了一個工廠類來建立這些對象,該類中的Factory::NewJsObject就是用來建立這些對象的。
下面列出了所有使用該類/方法的方法。
V8引擎中的類並沒有直接使用這個工廠類,而是添加了另一層封裝,通過Heap類調用該工廠類。
訪問者模式:
維基百科上這樣解釋觀察者模式:
觀察者設計模式是將演算法和演算法處理的對象分開的一種方式。這種分離可以在不修改結構本身的情況下,將新的操作添加到已有的對象結構上。這是一條遵循open/closed準則的方式。
與原廠模式相似,訪問者模式也為實現添加了封裝層。這樣讓其代碼更加可讀且可維護。
V8源碼中許多類都實現了訪問者模式。
即使V8開發人員必須最佳化執行效率,他們也不在乎添加到代碼中的封裝層。使用設計模式和添加一些C++的機制會增加一些封裝,所以的確會對效率有影響。但這對效率的影響僅佔一小部分,更多的影響來自該應用使用的設計決策。
V8中針對執行效率方面的設計決策
1. 隱藏類和快速屬性訪問。
JavaScript是一種動態程式設計語言:可以在對象運行時為對象添加或刪除熟悉。這意味著很容易改變對象的屬性。
JSFunction和JSValue的父類都是JSObject,JSFunction用來表示一個javascript函數,JSValue用來表示一個javascript值。但沒有繼承自JSObject的類,用以表示Function或Value這樣的Class。許多JavaScript引擎使用詞典類型的資料結構來儲存這些對象的熟悉,訪問每個屬性都需要動態尋找並解析屬性在記憶體中的位置。
這種方式導致JavaScript在訪問物件變數的屬性時,比在Java或Smalltalk中要慢。在這些語言中,實列變數分配的位置是固定的,即由編譯器根據對象的類定義中的布局,在該對象在記憶體中的位置加上固定的位移位置。因此訪問這些屬性僅僅是記憶體上的讀取或儲存,而這種操作通常只需一條指令。
V8使用隱藏類概念來降低訪問JavaScript屬性所消耗的時間。V8不使用動態查詢來訪問屬性,而是在幕後建立隱藏類。
2. 動態生產機器碼
在首次執行時,V8就將JavaScript源碼直接編譯成機器碼,沒有中間位元組碼,沒有解譯器。屬性訪問由內聯的緩衝代碼處理,V8執行時可能會有其他機器指令修改這些緩衝代碼。
3. 高效的垃圾收集器
在執行過程中,V8會重新獲得廢棄對象的記憶體,即記憶體回收。為了保證擁有較快的對象分類、較短的記憶體回收停頓,以及沒有記憶體片段。V8使用了停頓、分代、精確記憶體回收行程。這意味著V8使用了:
#include <stdio.h>
#include <time.h>
#include <opencv2/opencv.hpp>
#include <opencv/cv.h>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
#include <io.h>
using namespace std;
using namespace cv;
void getFiles( string path, vector<string>& files);
void getBubble(Mat& trainingImages, vector<int>& trainingLabels);
void getNoBubble(Mat& trainingImages, vector<int>& trainingLabels);
int main()
{
//擷取訓練資料
Mat classes;
Mat trainingData;
Mat trainingImages;
vector<int> trainingLabels;
getBubble(trainingImages, trainingLabels);
getNoBubble(trainingImages, trainingLabels);
Mat(trainingImages).copyTo(trainingData);
trainingData.convertTo(trainingData, CV_32FC1);
Mat(trainingLabels).copyTo(classes);
//配置SVM訓練器參數
CvSVMParams SVM_params;
SVM_params.svm_type = CvSVM::C_SVC;
SVM_params.kernel_type = CvSVM::LINEAR;
SVM_params.degree = 0;
SVM_params.gamma = 1;
SVM_params.coef0 = 0;
SVM_params.C = 1;
SVM_params.nu = 0;
SVM_params.p = 0;
SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.01);
//訓練
CvSVM svm;
svm.train(trainingData, classes, Mat(www.huachengjpt.com), Mat(), SVM_params);
//儲存模型
svm.save("svm.xml");
cout<<"訓練好了!!!"<<endl;
getchar();
return 0;
}
void getFiles( string path, vector<string>& files )
{
long hFile = 0;
struct _finddata_t www.8555388.cn/ fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append(www.yibaoyule1.com"\\*").c_str(),&fileinfo)) != -1)
{
do
{
if((fileinfo.attrib & _A_SUBDIR))
在記憶體回收迴圈期間停止程式的執行。
在大多數垃圾迴圈中,只處理對象堆的一部分。這最大化降低了停頓對應用的影響。
記錄所有對象和指標在記憶體中的位置,避免了將對象作為指標識別而導致的記憶體流失。
結論:
出於效率因素而不使用物件導向或設計模式,這是一個錯誤的觀念。這樣只會獲得數毫秒的最佳化,卻失去了代碼的可讀性和可維護性。
V8是Google開源的一個高效能JavaScript引擎