SPL代碼優(yōu)化技巧

SPL是一種面向結(jié)構(gòu)化數(shù)據(jù)計(jì)算的程序設(shè)計(jì)語(yǔ)言,集算器是SPL語(yǔ)言的java實(shí)現(xiàn),采用網(wǎng)格式編程形式提供了編碼和調(diào)試的IDE環(huán)境,語(yǔ)法比Java和SQL更為簡(jiǎn)單易懂,開(kāi)發(fā)效率更高。本文將從集算器的實(shí)現(xiàn)原理出發(fā)列舉一些可以提升計(jì)算性能的小技巧。

公司主營(yíng)業(yè)務(wù):做網(wǎng)站、網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。成都創(chuàng)新互聯(lián)推出澄江免費(fèi)做網(wǎng)站回饋大家。

1數(shù)據(jù)類型

1.1 數(shù)值

????????SPL里的數(shù)值類型有Integer、Long、Double、BigDecimal。其中BigDecimal雖然能夠表示任意精度的數(shù)據(jù),但計(jì)算速度比其它數(shù)類型慢很多,占用的內(nèi)存也大很多,因此在其它數(shù)字類型能夠滿足精度要求時(shí),使用其它數(shù)類型代替BigDecimal能夠顯著提升計(jì)算效率。

????????實(shí)際案例中,在使用JDBC讀取數(shù)據(jù)庫(kù)數(shù)據(jù)時(shí),有些數(shù)據(jù)庫(kù)的JDBC對(duì)于低精度數(shù)值也返回BigDecimal,這樣,在做性能優(yōu)化時(shí)就可以檢查一下是否可以轉(zhuǎn)為其它類型,從而提升性能。

1.2 字符串

???????? Java的字符串對(duì)象String占用空間較大,一個(gè)長(zhǎng)度為0的字符串占用40多個(gè)字節(jié),而Integer、Long只占用16個(gè)字節(jié)。同時(shí)字符串的比較運(yùn)算、哈希運(yùn)算也比Integer、Long慢。

???????? 另外,數(shù)據(jù)從硬盤讀入生成java對(duì)象,其占用的內(nèi)存大小往往是其占用的硬盤大小的數(shù)倍甚至十倍以上(如果硬盤存儲(chǔ)使用了壓縮技術(shù)差距會(huì)更大)。這種情況可能直接導(dǎo)致不太大的數(shù)據(jù)文件在讀成java對(duì)象時(shí)發(fā)生內(nèi)存溢出,這時(shí)如果不能減少內(nèi)存占用量就只能使用外存計(jì)算了。而通常外存計(jì)算的復(fù)雜度遠(yuǎn)大于內(nèi)存計(jì)算,同時(shí)也導(dǎo)致性能會(huì)下降很多。

????????那么,有沒(méi)有什么方法能夠減少內(nèi)存占用同時(shí)又能提高計(jì)算效率呢?

????????一個(gè)常用的方法就是枚舉串序號(hào)化,比如下面一個(gè)事實(shí)表的數(shù)據(jù):

SPL 代碼優(yōu)化技巧 ?

????????性別、地區(qū)這類枚舉型的字段,可以建立一個(gè)對(duì)應(yīng)表把性別、地區(qū)值轉(zhuǎn)換為序號(hào)1、2、…,這樣事實(shí)表中性別字段就可以只保存對(duì)應(yīng)的序號(hào),地區(qū)也是一樣。轉(zhuǎn)換后數(shù)據(jù)如下:

SPL 代碼優(yōu)化技巧 ?

?

SPL 代碼優(yōu)化技巧 ?

?

SPL 代碼優(yōu)化技巧 ?

????????這樣一來(lái),我們就可以做到減少內(nèi)存占用,并且提高計(jì)算效率,因?yàn)閿?shù)字的比較、分組等操作比字符串的要快很多。在輸出結(jié)果時(shí),可以根據(jù)需要再把序號(hào)轉(zhuǎn)化為串,也就是使用序號(hào)直接按位置到代碼表中找到相應(yīng)的記錄進(jìn)行替換。

2序表結(jié)構(gòu)

2.1 行追加

???????? 序表類似數(shù)據(jù)庫(kù)中的表,但是卻是有順序的。序表數(shù)據(jù)在內(nèi)存中用一個(gè)連續(xù)的數(shù)組保存。一般情況下,為序表分配內(nèi)存時(shí)會(huì)多預(yù)留一些空間來(lái)應(yīng)付可能的增長(zhǎng),以免每次追加數(shù)據(jù)時(shí)都重新分配內(nèi)存,不過(guò)也不可能預(yù)留太多空間而浪費(fèi)內(nèi)存。

????????基于這個(gè)原來(lái),為序表頻繁地追加記錄,會(huì)導(dǎo)致這個(gè)數(shù)組長(zhǎng)度不斷地變長(zhǎng),原先為這個(gè)數(shù)組分配的空間也要擴(kuò)大。而擴(kuò)大內(nèi)存分配不是一件很簡(jiǎn)單的事情,需要分配一塊更大的空間,然后將原空間內(nèi)的數(shù)據(jù)復(fù)制過(guò)來(lái)。尋找空間和復(fù)制數(shù)據(jù)都要占用 CPU 時(shí)間,而且常常比運(yùn)算本身的消耗都大。

????????因此,如果事先知道行數(shù),一次性把序表創(chuàng)建出來(lái),那只需要在一開(kāi)始分配一次內(nèi)存就行了。即便序表中的字段值需要一些步驟才能計(jì)算出來(lái),那也應(yīng)該先new出序表后再去修改記錄的字段值,而不要計(jì)算一行插入一行。而對(duì)于修改記錄字段值的方法SPL提供了很多途徑。

????????假設(shè)我們想生成一個(gè)20行 2列的斐波那契數(shù)列序表,第一列key為行號(hào),即 1,2,3,…;第二列 value 為值。斐波那契數(shù)列數(shù)列的規(guī)則是:第 1、第 2 行取值為 1,從第 3 行起,取值為前兩行之和。這個(gè)運(yùn)算需要一步步實(shí)現(xiàn),動(dòng)態(tài)追加數(shù)據(jù)就是很自然的想法了:

SPL 代碼優(yōu)化技巧 ?

不過(guò),序表一次性產(chǎn)生性能更好,即使計(jì)算本身仍然需要一步步實(shí)現(xiàn):

SPL 代碼優(yōu)化技巧 ?

?

2.2 列追加

????????擴(kuò)充序表,除了一行行追加數(shù)據(jù),還有可能會(huì)改變數(shù)據(jù)的結(jié)構(gòu),增加每行數(shù)據(jù)中的字段,也就是所謂的列追加。列追加比行追加要更為復(fù)雜,序表本身是一個(gè)大數(shù)組,其中的每一行是一條記錄,物理實(shí)現(xiàn)上也是一個(gè)數(shù)組。因?yàn)閿?shù)據(jù)結(jié)構(gòu)很少改變,創(chuàng)建序表時(shí)不會(huì)在生成每行的數(shù)組時(shí)預(yù)留空間,否則內(nèi)存浪費(fèi)就太多了(因?yàn)槊恳恍卸家A(yù)留)?;谶@種實(shí)現(xiàn)原理,如果出現(xiàn)列追加,就會(huì)發(fā)生前面說(shuō)的重新分配空間的情況,而且要針對(duì)每一行記錄進(jìn)行,再將原記錄數(shù)據(jù)抄過(guò)來(lái),可以想見(jiàn),這個(gè)動(dòng)作的時(shí)間成本有多大,甚至經(jīng)常會(huì)遠(yuǎn)遠(yuǎn)超過(guò)追加那個(gè)列后要做的計(jì)算。

????????SPL為序表提供了追加列的功能,這會(huì)帶來(lái)方便性,但在關(guān)注性能時(shí)卻要慎用。不得不用時(shí),也應(yīng)該如上所述,一次性把需要追加的列都加上,不要一遍遍地追加。對(duì)于當(dāng)時(shí)無(wú)法計(jì)算出字段值的列可以先填成空值,以后再用其它函數(shù)去修改字段值。

????????最常見(jiàn)的情況,從數(shù)據(jù)庫(kù)取出的序表后,如果事先知道要再derive出新的一列xxx,那么可以在寫SQL時(shí)多寫一個(gè)null as xxx,這樣在query時(shí)就直接把所需的字段都產(chǎn)生了,不用再做一次derive了。

????????例如,要從數(shù)據(jù)表sales中取出字段ORDERDATE,AMOUNT并按ORDERDATE排序,然后追加一列計(jì)算AMOUNT的累計(jì)值。一般先讀出再追加列的自然寫法:

SPL 代碼優(yōu)化技巧 ?

而用 SQL 語(yǔ)句先把列生成好的寫法:

SPL 代碼優(yōu)化技巧 ?

????????

2.3 引用記錄

????????針對(duì)前面兩種調(diào)整序表結(jié)構(gòu)的優(yōu)化思路,出發(fā)點(diǎn)都是減少new、derive函數(shù)中抄字段值的動(dòng)作。除此之外,SPL還支持對(duì)象引用,字段取值可以是另一條記錄。這樣,在SPL中,大多數(shù)情況沒(méi)必要像SQL那樣在新結(jié)果集中把字段抄一遍,為了保持原有整條記錄一起參與運(yùn)算,只要用引用方式來(lái)寫就可以了。這樣不僅性能更好而且空間占用也少。

????????上面用derive追加AMOUNT累計(jì)值的要求可以用new函數(shù)實(shí)現(xiàn),new創(chuàng)建一個(gè)新序表,SRC字段引用原紀(jì)錄,CUMULATE字段存儲(chǔ)累計(jì)值,寫法如下:

SPL 代碼優(yōu)化技巧 ?

?

3循環(huán)函數(shù)

3.1 用循環(huán)函數(shù)代替循環(huán)語(yǔ)句

????????SPL的網(wǎng)格程序提供了循環(huán)語(yǔ)句for和分支語(yǔ)句if來(lái)實(shí)現(xiàn)復(fù)雜的運(yùn)算邏輯。運(yùn)行時(shí),由于網(wǎng)格的執(zhí)行次序是動(dòng)態(tài)解釋的,因此大量使用循環(huán),會(huì)導(dǎo)致執(zhí)行的網(wǎng)格過(guò)多,在網(wǎng)格的動(dòng)態(tài)解釋上就要花費(fèi)大量的時(shí)間。

????????除了循環(huán)語(yǔ)句,SPL還提供了循環(huán)函數(shù),可以對(duì)付大多數(shù)需要使用for語(yǔ)句的場(chǎng)景。對(duì)于計(jì)算步驟不太復(fù)雜,對(duì)性能要求高的運(yùn)算應(yīng)該盡量使用循環(huán)函數(shù)來(lái)完成。類似地,能用if 函數(shù)的場(chǎng)景也盡量不要用if語(yǔ)句。

????????1.2節(jié)中列舉的計(jì)算斐波那契數(shù)列的例子可以改寫為如下:

SPL 代碼優(yōu)化技巧 ?

????????其中#表示當(dāng)前循環(huán)到哪條記錄,第一條記錄對(duì)應(yīng)的#是1,依次遞增。value[-1]表示上一條記錄的value值,value[-2]表示上前數(shù)第二條記錄的value值。

?

????????eval函數(shù)每次執(zhí)行都要把參數(shù)指定的表達(dá)式字符串解析成表達(dá)式,然后再執(zhí)行,如果eval函數(shù)在循環(huán)里執(zhí)行,過(guò)多地把表達(dá)式字符串解析成表達(dá)式會(huì)花費(fèi)大量的時(shí)間,如果表達(dá)式字符串不是變的則可以使用宏替換代替eval。

3.2 常量放在循環(huán)外

????????把循環(huán)里常量的產(chǎn)生放到循環(huán)外,也可以對(duì)性能優(yōu)化提供幫助。例如選出北京, 上海, 深圳地區(qū)的銷售記錄,比較“自然”的寫法是:

SPL 代碼優(yōu)化技巧 ?

????????因?yàn)镾PL的序列是可以被修改的,所以表達(dá)式["北京","上海","深圳"]每計(jì)算一次都會(huì)產(chǎn)生一個(gè)新序列。如果像上面這樣把["北京","上海","深圳"]放在循環(huán)函數(shù)select里,那么在執(zhí)行時(shí)將會(huì)產(chǎn)生A2長(zhǎng)度個(gè)序列。如果循環(huán)次數(shù)多,這些不必要的運(yùn)算將消耗大量時(shí)間。因此,注重性能的寫法應(yīng)該如下:

SPL 代碼優(yōu)化技巧 ?

?

3.3 警惕循環(huán)套循環(huán)

????????警惕循環(huán)函數(shù)中再有循環(huán)函數(shù),這些代碼看起來(lái)很簡(jiǎn)單,但幾層循環(huán)下來(lái),實(shí)際計(jì)算量會(huì)以幾何級(jí)數(shù)放大。這雖然是個(gè)常識(shí),但有時(shí)也會(huì)被忽略,因此能在循環(huán)外做的事不要放到循環(huán)內(nèi)。特別地,尤其要警惕在循環(huán)內(nèi)讀文件和訪問(wèn)數(shù)據(jù)庫(kù)這種超級(jí)耗時(shí)的動(dòng)作。

4代碼習(xí)慣

4.1 釋放內(nèi)存

???????? Java在內(nèi)存不足時(shí)性能會(huì)急劇下降。所以要及時(shí)釋放內(nèi)存,SPL沒(méi)有刪除變量釋放內(nèi)存的語(yǔ)句,只需把變量或單元格的值設(shè)為空即可,也可以用clear語(yǔ)句清除一片格子。例子如下:

SPL 代碼優(yōu)化技巧 ?

???????? 以=開(kāi)頭單元格是計(jì)算格,表達(dá)式的返回值會(huì)保存在單元格上,以>開(kāi)頭的單元格是執(zhí)行格,表達(dá)式的返回值不會(huì)保存。cs.select和cs.join是給游標(biāo)附加運(yùn)算,不會(huì)產(chǎn)生新的游標(biāo)所以返回值可以不用保存,A7格為釋放讀出的PART數(shù)據(jù),也可以用clear語(yǔ)句把A1到A5之間的單元格值都清空,只需要把A7格代碼替換如下:

SPL 代碼優(yōu)化技巧 ?

?

4.2 代碼緊湊

???????? for 和if的代碼塊,可以直接寫到同一行上,沒(méi)有必要像Java那樣換一行再寫。SPL的網(wǎng)絡(luò)已經(jīng)能夠清晰地拆分出這些語(yǔ)句了。解釋器掃描空白格也需要時(shí)間,因此對(duì)于含有循環(huán)語(yǔ)句的程序,如果循環(huán)次數(shù)特別多,應(yīng)該讓代碼緊湊一些,刪除空白的行和列以減少格子數(shù)量,從而提高解釋器的效率。

???????? 下面以獲取每天第一條銷售記錄為例,介紹一下SPL的代碼塊規(guī)則,sales是銷售記錄游標(biāo)參數(shù),按ORDERDATE有序。

SPL 代碼優(yōu)化技巧 ? ? ? ? ? ? ?

????????單元格的代碼塊為單元格所在行及其正下和左下單元格都為空白格的行,上面例子中A2格for的代碼塊為[B2:F5]。B2格if的代碼塊為[C2 : F2],if代碼塊的下一行和if所在格同列的單元格B3為else,并且B3左面的格子都是空白格,則B3格為B2格的else分支,B3格的代碼塊為[C3 : F5]。else也可以和對(duì)應(yīng)的if同行,寫在if右面的單元格上。

網(wǎng)站名稱:SPL代碼優(yōu)化技巧
文章分享:http://muchs.cn/article28/jojicp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、服務(wù)器托管、移動(dòng)網(wǎng)站建設(shè)、建站公司、用戶體驗(yàn)、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司