




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
LoadRunner測試SQL語句性能本次通過loadRunner錄制SQLServer介紹一下如何測試一個sql語句或存儲過程的執行性能。主要分如下幾個步驟完成:第一步、測試準備第二步、配置ODBC數據源第三步、錄制SQL語句在SqlServer查詢分析器中的運行過程第四步、優化錄制腳本,設置事務第五步、改變查詢數量級查看SQL語句的性能第六步、在controller中運行腳本下面開始具體的介紹:測試準備階段我們首先要確認測試數據庫服務器:我們可以在本地安裝SQLSERVER數據庫服務端及客戶端,也可以確定一臺裝好的SQLSERVER服務器。接下來,準備測試數據:對數據庫測試時我們要考慮的不是SQL語句是否能夠正確執行,而是在某數量級的情況下SQL語句的執行效率及數據庫服務的運行情況,所以我們分別準備不同數量級的測試數據,即根據實際的業務情況預估數據庫中的記錄數,在本次講解中我們不考慮業務邏輯也不考慮數據表之間的關系,我們只建立一張表,并向此表中加入不同數量級的數據,如分別加入1000條、10000條、50000條、100000條數據查看某SQL語句的執行效率。在查詢分析器中運行如下腳本:--創建測試數據庫createdatabaseloadrunner_test;useloadrunnertest--創建測試數據表createtabletest_table(usernamevarchar(50),sexint,ageint,addressvarchar(100),postint)--通過一段程序插入不同數量級的記錄,具體的語法在這里就不多說了declare@iintset@i=0while@i<1000 /循環1000次,可以根據測試數據情況改變插入條數beginBEGINTRANT1insertintotest_table(username,sex,age,address,post)values(戶瑞海'+cast(@iasvarchar),@i—1,@i+1,'北京市和平里'+cast(@iasvarchar)+'號',123456);IF@@ERROR<>0beginrollback;select@@errorendelsebegincommit;set@i= @i+1endend好了,執行完上述語句后,建立的數據表中已經有1000條記錄了,下面進行第二步的操作,配置ODBC數據源,為了能讓loadrunner能夠通過ODBC協議連接到我們建立的SQLSERVER數據路,我們需要在本機上建立ODBC數據源,建立方法如下:控制面板一性能和維護一管理工具一數據源(ODBC)--添加,在列表中選擇SQLSERVER點擊完成,根據向導輸入數據源名稱,鏈接的服務器,下一步,輸入鏈接數據庫的用戶名和密碼,更改鏈接的數據庫,完成ODBC的配置,如果配置正確的話,在最后一步點擊“測試數據源”,會彈出測試成功的提示。配置好ODBC數據源后就要錄制SQL語句在查詢分析器中的執行過程了:1、打開loadrunner,選擇ODBC協議2、 在startrecording中的勺applicationtype選擇Win32application;programtorecord中錄入SQLSERVER查詢分析器的路徑“..\安裝目錄\isqlw.exe”3、 開始錄制,首先通過查詢分析器登錄SQLSERVER,在打開的查詢分析器窗口中輸入要測試的SQL語句口“select*fromtest_table;”4、 在查詢分析器中執行該語句,執行完成后,結束錄制好了,現在就可以看到loadrunner生成的腳本了(由于腳本過長,在這里就不粘貼了,有需要的朋友可以加我QQ,我把腳本發給你們),通過這些語句,我們可以看出,登錄數據庫的過程、執行SQL語句的過程。接下來,我們來優化腳本,我們分別為數據庫登錄部分和執行SQL語句的部分加一個事物,在增加一個double的變量獲取事務執行時間,簡單內容如下:Action(){doubletrans_time;/定義一個double型變量用來保存事務執行時間lr_start_transaction("sqserver_login");/設置登錄事務的開始lrd_init(&InitInfo,DBTypeVersion); //初始化鏈接(下面的都是loadrunner生成的腳本了,大家可以通過幫助查到每個函數的意思)lrd_open_context(&Ctx1,LRD_DBTYPE_ODBC,0,0,0);lrd_db_option(Ctx1,0T_0DBC_0V_0DBC3,0,0);lrd_alloc_connection(&Con1,LRD_DBTYPE_ODBC,Ctx1,0/*Unused*/,0);trans_time=lr_get_transaction_duration("sqserver_login");//獲得登錄數據庫的時間lr_output_message("sqserver_login事務耗時%f秒",trans_time);//輸出該時間lr_end_transaction("sqserver_login",LR_AUTO);/結束登錄事務lr_start_transaction("start_select");//開始查詢事務lrd_cancel(0,Csr2,0/*Unused*/,0);lrd_stmt(Csr2,"select*fromtest_table;\r\n",-1,1,0/*None*/,0);//此句為執行的SQLlrd_bind_cols(Csr2,BCInfo_D42,0);lrdfetch(Csr2,-10, 1, 0,PrintRow24,0);trans_time=lr_get_transaction_duration("start_select");//獲得該SQL的執行時間lr_output_message("start_select事務耗時%f秒",trans_time);//輸出該時間lrendtransaction("startselect",LRAUTO);//結束查詢事務優化后,在執行上述腳本后,就可以得到登錄到數據庫的時間及運行select*fromtest_table這條語句的時間了,當然我們也可以根據實際情況對該條語句進行參數化,可以測試多條語句的執行時間,也可以將該語句改為調用存儲過程的語句來測試存儲過程的運行時間。接下來把該腳本在controller中運行,設置虛擬用戶數,設置集合點,這些操作我就不說了,但是值得注意的是,沒有Mercury授權的SQLSERVER用戶license,在運行該腳本時回扌報錯,提示“YoudonothavealicenseforthisVusertype.PleasecontactMercuryInteractivetorenewyourlicense”我們公司窮啊買不起loadrunner,所以我也無法繼續試驗,希望有license朋友們監控一下運行結果!最起碼在VUGen中運行該腳本我們可以得到任意一個SQL語句及存儲過程的執行時間,如果我們測試的B/S結構的程序,我們也可以通過HTML協議錄制的腳本在CONTROLLER中監控SQLSERVER服務器的性能情況,這樣兩方面結合起來就可以對數據庫性能做一個完整的監控了。本人對LOADRUNNER也是在摸索中,如果文章有寫的不對,或理解錯誤的地方請指出,不甚感激。(以上言論僅代表作者的個人觀點,不代表51Testing觀點)/*需要的表結構如下CREATETABLE'test_data'('order_id'BIGINTUNSIGNEDNOTNULLCOMMENT'Ordernumbers.Mustbeunique.','status'BOOLNOTNULLDEFAULT'O'COMMENT'Whetherdatahasbeenusedornot.Avalueof0meansFALSE.',、date_used'DATETIMENULLCOMMENT'Date/timethatthedatawasused.',UNIQUE('order_id'))ENGINE=innodbCOMMENT='LoadRunnertestdata';*/Action(){intrc;intdb_connection;//數據庫連接intquery_result;//查詢結果集MYSQL_RESchar**result_row;//查詢的數據衕char*server="localhost";char*user="root";char*password="123456";char*database="test";intport=3306;intunix_socket=NULL;intflags=0;//找到libmysql.dll的所在位置.rc=lr_load_dll("C:\\ProgramFiles\\MySQL\\MySQLServer5.1WbinWlibmysql.dll");if(rc!=0){lr_error_message("Couldnotloadlibmysql.dll");lr_abort();}//創建MySQL對象db_connection=mysql_init(NULL);if(db_connection==NULL){lr_error_message("Insufficientmemory");lr_abort();}//連接到MySQL數據庫rc=mysql_real_connect(db_connection,server,user,password,database,port,unix_socket,flags);if(rc==NULL){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}//向數據庫插入數據//此處的{ORDER_ID}是一個參數,簡單測試時可以用一個常數代替lr_save_string(lr_eval_string("INSERTINTOtest_data(order_id)VALUES({ORDER_ID})"),"paramInsertQuery");rc=mysql_query(db_connection,lr_eval_string("{paramInsertQuery}"));if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}//從數據庫讀取一個數據并顯示rc=mysql_query(db_connection,"SELECTorder_idFROMtest_dataWHEREstatusISFALSELIMIT1");if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}query_result=mysql_use_result(db_connection);if(query_result==NULL){lr_error_message("%s",mysql_error(db_connection));mysql_free_result(query_result);mysql_close(db_connection);lr_abort();}//如果結果集包含多行數據,需要多次調用mysql_fetch_row直到返回NULLresult_row=(char**)mysql_fetch_row(query_result);if(result_row==NULL){lr_error_message("Didnotexpecttheresultsettobeempty");mysql_free_result(query_result);mysql_close(db_connection);lr_abort();}//保存參數,用于刪除這行數據lr_save_string(result_row[O],"paramOrderlD");lr_output_message("OrderIDis:%s",lr_eval_string("{paramOrderID}"));mysql_free_result(query_result);//在事務里更新一行數據,需要用InnoDB引擎rc=mysql_query(db_connection,"BEGIN");//啟動事務if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}//使用"FORUPDATE"鎖住要更新的數據行rc=mysql_query(db_connection,"SELECTorder_idFROMtest_dataWHEREstatusISFALSELIMIT1FORUPDATE");if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}query_result=mysql_use_result(db_connection);if(query_result==NULL){lr_error_message("%s",mysql_error(db_connection));mysql_free_result(query_result);mysql_close(db_connection);lr_abort();}result_row=(char**)mysql_fetch_row(query_result);if(result_row==NULL){lr_error_message("沒有查詢到結果");mysql_free_result(query_result);mysql_close(db_connection);lr_abort();}lr_save_string(result_row[O],"paramOrderID");lr_output_message("OrderIDis:%s",lr_eval_string("{paramOrderID}"));mysql_free_result(query_result);lr_save_string(lr_eval_string("UPDATEtest_dataSETstatus=TRUE,date_used=NOW()WHEREorder_id='{paramOrderID}'"),"paramUpdateQuery");rc=mysql_query(db_connection,lr_eval_string("{paramUpdateQuery}"));if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}rc=mysql_query(db_connection,"COMMIT");//提交事務if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}//再次查找數據,應該為空了,因為前面的事務更新了標志rc=mysql_query(db_connection,"SELECTorder_idFROMtest_dataWHEREstatusISFALSELIMIT1");if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}query_result=mysql_use_result(db_connection);if(query_result==NULL){lr_error_message("%s",mysql_error(db_connection));mysql_free_result(query_result);mysql_close(db_connection);lr_abort();}result_row=(char**)mysql_fetch_row(query_result);if(result_row==NULL){lr_output_message("Resultsetisemptyasexpected");mysql_free_result(query_result);}else{lr_error_message("Didnotexpecttheresultsettocontainanyrows");mysql_free_result(query_result);mysql_close(db_connection);lr_abort();}//刪除數據lr_save_string(lr_eval_string("DELETEFROMtest_dataWHEREorder_id='{paramOrderID}'"),"paramDeleteQuery");rc=mysql_query(db_connection,lr_eval_string("{paramDeleteQuery}"));if(rc!=0){lr_error_message("%s",mysql_error(db_connection));mysql_close(db_connection);lr_abort();}//釋放MySQL資源mysql_close(db_connection);return0;}本文章來源于西盟軟件站【/r/】詳細地址:/article/175/data/2009/2009070819880.html(轉)LoadRunner測試過程中調用dll文件的制作與使用上一篇/下一篇2009-01-1716:35:36/個人分類:LoadRunner查看(109)/評論(0)/評分(0/0)在Windows操作系統中使用DLL有很多優點,最主要的一點是多個應用程序、甚至是不同語言編寫的應用程序可以共享一個DLL文件,真正實現了資源"共享”,大大縮小了應用程序的執行代碼,更加有效的利用了內存;使用DLL的另一個優點是DLL文件作為一個單獨的程序模塊,封裝性、獨立性好,在軟件需要升級的時候,開發人員只需要修改相應的DLL文件就可以了,而且,當DLL中的函數改變后,只要不是參數的改變,程序代碼并不需要重新編譯。這在編程時十分有用,大大提高了軟件開發和維護的效率。在LR下也可以直接調用動態鏈接庫文件,針對一些使用LR腳本編寫比較煩瑣的方法可以考慮此方法(比如各種加解密算法的實現,數據庫的操作等),并能夠使測試腳本簡單明了。鑒于此,本人初次嘗試了如何制作DLL文件并在LR中使用。1、dll文件的制作在VisualC++6.0開發環境下,打開File-New-Project選項,可以選擇Win32Dynamic-LinkLibrary來創建一個名為dllfortest的空的dll工程(這只是方法之一)。在該項目中新建一個dllfortest.h和dllfortest.cpp文件,文件的內容如下://dllfortest.hextern"C"_declspec(dllexport)intMax(inta,intb,intc);extern"C"_declspec(dllexport)intMin(inta,intb,intc);//dllfortest.cpp包含一個計算三個整數中最大值和最小值的方法#include"dllfortest.h"intMax(inta,intb,intc)intRes;Res=(a>b?a:b)>c?(a>b?a:b):c;returnRes;}intMin(inta,intb,intc){intRes;Res=(a>b?b:a)>c?c:(a>b?b:a);returnRes;}該動態鏈接庫編譯成功后,打開dllfortest工程目錄下的debug目錄下,可以看到生成了一個dllfortest.dll文件,這就是我們想要的文件。2、dll文件在LR中的調用打開LRVUGenerator,選擇CVuser協議(或其他支持C的協議),進入編輯界面。Action部分如下所示:Action(){lr_load_dll("dllfortest.dll");lr_message("MaxResultis%d",Max(100,200,67));lr_message("MinResultis%d",Min(55,97,63));return0;}將dllfortest.dll文件復制到腳本所在的目錄(如果不復制的話,lr_load_dll的參數應該寫成dll文件的絕對路徑),如果編譯沒有報錯的話,就可以直接運行了。運行結果如下:VirtualUserscrptstartedStartingactionvuser_init.Endingactionvuser_init.RunningVuser...Startingiteration1.StartingactionAction.MaxResultis200MinResultis55EndingactionAction.Endingiteration1.EndingVuser...Startingactionvuser_end.Endingactionvuser_end.VuserTerminated.如果在腳本中用到了DLL文件中并不存在的方法名時,編譯也能通過,但是運行時LR會報錯,提示不存在該方法比如我們在腳本中添加一句:lr_message("MinResultis%d",Sum(55,97,63));//Sum方法并不存在運行時錯誤信息如下:Action.c(7):Error:Cinterpreterruntimeerror:Action.c(7):Error--Unresolvedsymbol:Sum.Action.c(7):Notify:CCItrace:Compiled_code(0):Action()這個例子并沒有體現出DLL文件調用的優點,因為調用的方法在LR中用C直接就可以完成,但涉及到LR中完不成的任務時,或許dll文件的作用就體現出來了example:LoadRunner提供了功能強大的API集合,足夠應付大多數性能測試的需求。但在某些情況下,這些API仍然有覆蓋不到的地方。例如,我們有一個WEB應用,該應用有一個頁面輸入用戶的信息,為了安全起見,用戶輸入的信息在提交之前都要先進行加密處理,加密處理通過本地的COM組件實現。對這個要求而言,LoadRunner的現有API不能提供直接支持,因為LoadRunner在錄制腳本時只錄制數據交互,因此,COM的加密處理過程是不能錄制下來的。在LoadRunner的腳本中,可能只有類似以下的語句描述了這個過程:web_url("userinfo","URL=http://testweb/userinfo.aspx","TargetFrame=","Resource=0","Referer=",LAST);web_submit_form("login","Snapshot=t4.inf",ITEMDATA,"Name=username","Value=4e92Sh6d394g",ENDITEM,"Name=password","Value=932A2hf34U18",ENDITEM,LAST);從腳本可以看到,輸入的數據是加密后的數據,但LR沒有錄制到加密過程。假設加密函數所在的DLL名為security.dll,用于加密的函數名為encode,則一種可能的對腳本的修改方法如下代碼所示。char*encode_username,*encode_password,*orgin_username,*orgin_password;char*uservalue,passvalue;intret;web_url("userinfo","URL=http://testweb/userinfo.aspx","TargetFrame=","Resource=0","Referer=",LAST);orgin_username=lr_eval_string(“{username}”);〃獲取參數的值orgin_password=lr_eval_string(“{password}”);ret=lr_load_dll(“security.dll”); 〃加載DLL庫encode(origin_username,encode_username);〃調用encode函數encode(origin_password,encode_password);sprintf(uservalue,“Value=%s”,encode_username);sprintf(passvalue,“value=%s”,encode_password);web_submit_form("login","Snapshot=t4.inf",ITEMDATA,"Name=username",uservalue,ENDITEM,"Name=password",passvalue,ENDITEM,LAST);注意:有些腳本錄制需要相應的patch的支持,如錄制DotNet編寫的應用程序你需要把lr78安裝盤\Patches\Trap_for_.net_patch文件夾中trpfnc32.32dll拷貝到loadrunner'bin路徑下,才能正常工作。[轉貼]LoadRunner下DLL的調用場景介紹最近在做類似于QQ的通信工具的性能測試時發現了一些問題,現總結出來與大家分享一下。希望大家在使用LoadRunner時不僅僅停在只是錄制/播放腳本,而全面提升腳本的編程技術,解決復雜場景。本次測試中碰到的問題是這樣的,在消息的傳送過程中遇到了DEC加密的過程,LoadRunner錄制到的全是加密的消息,比如我錄制了某一個用戶的登陸,發送消息,退出,但由于是加密的,只能單個用戶使用,但如果我想并發多少個用戶就存在很多問題,最直接的一個問題就是用戶名是加密的,密碼是加密的,當然你可以說讓程序那里注掉加密的代碼進行明碼的測試,當然也是一種辦法。但程序組提出了要使用更真實的方法來模擬,這時就必需使用下面介紹的方法。一開始是直接把API移植到LoadRunner中來,不過由于加密算法異常復雜,有幾層循環,而腳本是解釋執行的,進行一次加密運算可能需要好幾分鐘,當然在腳本里可以把腳本本身運行的時間去掉,但這樣做顯然沒有直接調用DLL來的效率高。由于程序組比較忙,所以無法提供DLL給測試,所以測試組完成了DLL的編寫,并在LoadRunner中調用成功,高效的完成了用戶信息加密,參數關聯,成功的完成了測試。動態鏈接庫的編寫在VisualC++6.0開發環境下,打開FileNewProject選項,可以選擇Win32DynamicLinkLibrary建立一個空的DLL工程。Win32Dynamic-LinkLibrary方式創建Non-MFCDLL動態鏈接庫每一個DLL必須有一個入口點,這就象我們用C編寫的應用程序一樣,必須有一個WINMAIN函數一樣。在Non-MFCDLL中DllMain是一個缺省的入口函數,你不需要編寫自己的DLL入口函數,用這個缺省的入口函數就能使動態鏈接庫被調用時得到正確的初始化。如果應用程序的DLL需要分配額外的內存或資源時,或者說需要對每個進程或線程初始化和清除操作時,需要在相應的DLL工程的.CPP文件中對DIIMain()函數按照下面的格式書寫。BOOLAPIENTRYDllMain(HANDLEhModule,DWORDul_reason_for_call丄PVOIDIpReserved){switch(ul_reason_for_call){caseDLL_PROCESS_ATTACH:break;caseDLL_THREAD_ATTACH:break;caseDLL_THREAD_DETACH:break;caseDLL_PROCESS_DETACH:break;default:break;}returnTRUE;}參數中,hMoudle是動態庫被調用時所傳遞來的一個指向自己的句柄(實際上,它是指向_DGROUP段的一個選擇符);ul_reason_for_call是一個說明動態庫被調原因的標志,當進程或線程裝入或卸載動態鏈接庫的時候,操作系統調用入口函數,并說明動態鏈接庫被調用的原因,它所有的可能值為:DLL_PROCESS_ATTACH:進程被調用、DLL_THREAD_ATTACH:線程被調用、DLL_PROCESS_DETACH:進程被停止、DLL_THREAD_DETACH:線程被停止;IpReserved為保留參數。到此為止,DLL的入口函數已經寫了,剩下部分的實現也不難,你可以在DLL工程中加入你所想要輸出的函數或變量了。我們已經知道DLL是包含若干個函數的庫文件,應用程序使用DLL中的函數之前,應該先導出這些函數,以便供給應用程序使用。要導出這些函數有兩種方法,一是在定義函數時使用導出關鍵字_declspec(dllexport),另外一種方法是在創建DLL文件時使用模塊定義文件.Def。需要讀者注意的是在使用第一種方法的時候,不能使用DEF文件。下面通過兩個例子來說明如何使用這兩種方法創建DLL文件。1)使用導出函數關鍵字_declspec(dllexport)創建MyDll.dll,該動態鏈接庫中有兩個函數,分別用來實現得到兩個數的最大和最小數。在MyDll.h和MyDLL.cpp文件中分別輸入如下原代碼://MyDLL.hextern"C"_declspec(dllexport)intdesinit(intmode);extern"C"_declspec(dllexport)voiddesdone(void);extern"C"_declspec(dllexport)voiddes_setkey(char*subkey,char*key);extern"C"_declspec(dllexport)voidendes(char*block,char*subkey);extern"C"_declspec(dllexport)voiddedes(char*block,char*subkey);//MyDll.cpp
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- (8)-專題08 文學常識
- 造口產品培訓總結與展望
- 2025年教育部直屬高等教育支持保障系統非經營性資金教學設施采購合同
- 2025標準版商業店鋪租賃轉讓合同模板
- 2025蜂蜜生產養殖收購合同
- 采購丙綸織帶合同范本
- 防疫安全教育中班
- 2025聘請小說作者合同的范本
- 餐飲培訓公司合同范本
- 2025年標準合同范本
- 標志設計(全套課件88P)
- 2024年度工程檢測服務框架協議版
- 機器學習 課件 第7章 集成學習
- 視頻剪輯課件范文
- 健身房健身器材使用手冊
- 2022年福建省高考真題化學試題(解析版)
- 3.2有約必守 違約有責 課件-高中政治統編版選擇性必修二法律與生活
- 主管護師預測卷兒科護理專業實踐能力含答案
- 承包商入廠安全培訓試題附參考答案【完整版】
- 第23課《得道多助失道寡助》說課稿 統編版語文八年級上冊
- 江蘇省南京市鼓樓區2023-2024學年八年級下學期期中考試物理試題(解析版)
評論
0/150
提交評論