第五屆新能源汽車峰會暨展覽會2014

主辦單位:中國汽車工業協會、決策者會議策劃集團
支持機構:上海交通大學汽車工程研究院
時間:2014年11月12-14日 
地點:中國北京

【大會概況】

國家主席習近平5月24日指出,發展新能源汽車是邁向汽車強國的必由之路。從中央到地方,新能源汽車的推廣進入提速階段,新能源汽車補貼城市大幅擴容。

6月中旬,特斯拉CEO馬斯克表示,為了電動汽車技術的發展,特斯拉將開放其所有的專利。特斯拉專利技術的公開,能夠避免後來者在一些共性領域研發或測試的資源浪費,從而加速技術和商業模式的創新;加上不少汽車巨頭已經開始意識到新能源汽車市場的迅速興起而紛紛斥資研發與生產,新能源汽車市場的蓬勃拓展進程有望大大加快。

7月默克爾訪華,此行的一項重要議程就是啟動中德在電動車領域的合作的一個重要專案——中德電動汽車充電項目。在活動現場,工信部部長苗圩表示這一專案啟動是中德兩國在電動車產業領域合作得到推進的重要成果。

本屆大會結合行業趨勢發展,將研討新能源汽車發展,動力電池與動力能源供應模式,各類型商業運營模式創新,以及相關政策投資思想,引導消費者加深認知新能源汽車和推進新能源汽車產業發展方面,屆時300 多位全球新能源汽車有識之士歡聚一堂共同探討新能源汽車發展的各有關共性事項具有重要意義!

【上屆回顧】

第四屆綠色汽車大會於2013年10月9日至11日在中國北京海航萬豪酒店隆重召開。本次大會由亞洲最大的行業峰會主辦方——決策者會議策劃集團主辦, 得到中國汽車工業協會、中國高科技產業化研究會和韓國汽車工程研究院等國內外權威機構的指導與支持。

從中國和世界各地來的商界領袖、政府官員和產業密切相關部門的高層管理人員英相聚一堂,如電裝中國投資有限公司、德國大陸集團、上汽集團、艾爾維汽車工程技術、斯凱孚汽車技術有限公司和長安新能源汽車有限公司等等,共同探討行業熱門話題。

大會共吸引了來自30多個國家的200個參會代表、30位發言人、20家展商和55家媒體的參與。在全球與會代表的積極參與和回應下,它已經成長為亞洲第一的節能與新能源汽車行業盛會。

【本屆參數統計】

600+業內權威專家業內專業人士,400+專業參展觀眾,來自于320+行業知名企業單位,23+個國家
120+位參會代表來自語全球領先整車商,以及110+核心零部件提供商企業代表
40+ 知名權威發言人,為您敘說新能源汽車行業熱點資訊
16+ 小時商務交流機會,貫穿於雞尾酒會,小組討論,交流午宴及提問互動環節
6 場專題討論,為您深度解析關注行業熱點
5 年歷史,鑄就行業年度盛會

【展會特色】

實效性:展會期間將進行一對一會談、頒獎典禮,突出實效和品牌,做大做深供求雙方專業化配對洽談工作,為廣大業內人士及下游應用企業提供集中領略行業最新趨勢的機會。
品牌化:作為中國電動汽車行業最早商業化運作的峰會,歷經四年發展,無論是參會數量,還是贊助商數量,在國內同行業峰會中,都是雄踞前列,深受業界同仁的認可和讚揚,其知名度和美譽度在業內廣為流傳。成為中國電動汽車行業名副其實的第一會。 
國際化:往屆嘉賓有來自美國、日本、韓國、德國、丹麥、義大利、臺灣等國家和地區的國際企業參會,已經成為電動汽車行業的資訊分享、技術交流、貿易採購平臺。
專業化:是國內目前唯一的電動汽車行業的專業峰會之一,一年一屆。內容包含電動汽車(含混合動力)的整車、零部件、管理系統、充電站及相關配套設施等. 將吸引來自中國電動汽車企業超320家企業巨頭高層參觀,雲集政府機關行業協會,整車商,大學院校及研究院,零部件百強企業,核心技術設備提供商。
全媒體曝光:主辦方將基於網站、雜誌、微信、微博等多媒體平臺,在展前、展中、展後分別做全方位即時報導,預計將會實現超過10萬人次覆蓋。

【2014年新能源汽車頒獎典禮獎項設置】

年度優秀電動汽車電池生廠商獎
年度優秀綠色汽車諮詢公司獎
年度優秀綠色汽車解決方案提供商獎
終身成就獎
企業社會責任商獎
優秀核心零部件提供商獎
優秀綠色汽車服務商獎
優秀綠色汽車技術提供商獎

【展商評價】

“是一個尋找合作夥伴的理想場所,本次參展讓我們受益頗多,明年會一如既往支援綠色汽車大會!”
—— Shinry Technologies Co., Ltd

“通過很好的管道將我們的產品展現在客戶面前,非常滿意。”
—— AGC Automtive

“綠色汽車大會提供一個行業人士交流的平臺,參會參展企業眾多,達到了我們的參展期望值。”
—— Thermal Hazard Technology

“我們同時參加了峰會和展覽,非常值得推薦的活動!”
—— 捷特科

“非常滿意,無論是活動內容,參會嘉賓,還是規模層次都很出色,會推薦個同事。”
—— W.E.T. Automotive Systems (China) Ltd

會議官網:

聯絡人

邱玉芳
電話:021 63931899轉2041
傳真:021 6840 7632;郵編:200122
e-mail:
地址:上海長逸路15號復旦軟體園9樓

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

取代老舊公務車 英國政府大手筆採購 150 輛 Tesla Model S

    根據國外媒體報導,英國中央政府正在規劃一筆約 850 萬美元的預算,用來採購約 150 輛的 Tesla Model S 電動車,用來取代中央政府部門使用的老舊車輛。這 150 輛 Tesla S 服役後,將占英國中央政府機關用車約 30 %。   英國政府將會以每輛約 3 萬 3000 英鎊(約合台幣 171 萬 7600 元)的價格取得這批 Tesla S,雖然說已經比 Tesla Model S 在英國的正式售價 5 萬英鎊要便宜,但是仍然超出預算許多。   英國政府會採用 Tesla S 的主要原因是:跟 3 萬英鎊價格帶的其他電動車款相比(主要是 BMW i3,即便是 i3 Rex 增程版也只有 300 公里),Tesla Model S 的 250 英哩續航力(約 402 公里),相較之下的確是實用太多了。   (圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

一起玩轉微服務(12)——揭密starter

介紹

Spring Boot的starter主要用來簡化依賴用的,對於企業級開發中的與第三方的集成,可以通過一段簡單的配置來完成,這樣開發人員無需再對包依賴的問題頭疼。Spring Boot為我們提供了簡化企業級開發的絕大多數場景的starter pom,只需要指定需要配置的starter,Spring Boot會自動為我們提供配置好的bean。

通常流程

通常我們要搭建一個基於Spring的Web應用,我們需要做以下一些工作:

pom文件中引入相關jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相關jar …

配置web.xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 …

配置數據庫連接、配置spring事務

配置視圖解析器

開啟註解、自動掃描功能

配置完成後部署tomcat、啟動調試

……

花在搭建一個初始項目,可能一個小時就過去了或者半天就過了,但是用了SpringBoot之後一切都會變得非常便捷。

常用的starter

Spring Boot常用的starter(啟動器)包括:

  • Spring-boot-starter-logging :使用 Spring Boot 默認的日誌框架 Logback。
  • Spring-boot-starter-log4j :添加 Log4j 的支持。
  • Spring-boot-starter-web :支持 Web 應用開發,包含 Tomcat 和 Spring-mvc。
  • Spring-boot-starter-tomcat :使用 Spring Boot 默認的 Tomcat 作為應用服務器。
  • Spring-boot-starter-jetty :使用 Jetty 而不是默認的 Tomcat 作為應用服務器。
  • Spring-boot-starter-test :包含常用的測試所需的依賴,如 Junit、Hamcrest、Mockito 和 Spring-test 等。
  • Spring-boot-starter-AOP :包含 Spring-AOP 和 AspectJ 來支持面向切面編程(AOP)。
  • Spring-boot-starter-security :包含 Spring-security。
  • Spring-boot-starter-jdbc :支持使用 JDBC 訪問數據庫。
  • Spring-boot-starter-redis :支持使用 Redis。
  • Spring-boot-starter-data-mongodb :包含 Spring-data-mongodb 來支持 MongoDB。
  • Spring-boot-starter-data-jpa :包含 Spring-data-jpa、Spring-orm 和 Hibernate 來支持 JPA。
  • Spring-boot-starter-amqp :通過 Spring-rabbit 支持 AMQP。
  • Spring-boot-starter-actuator : 添加適用於生產環境的功能,如性能指標和監測等功能。

當然,如果有必要,也可以定製自己的starter。

起步依賴

在我們的pom文件裏面引入以下jar:

spring-boot-starter-web包自動幫我們引入了web模塊開發需要的相關jar包。

 

mybatis-spring-boot-starter幫我們引入了dao開發相關的jar包。 spring-boot-starter-xxx是官方提供的starter,xxx-spring-boot-starter是第三方提供的starter。

截圖看一下我們的mybatis-spring-boot-starter

可以看出mybatis-spring-boot-starter並沒有任何源碼,只有一個pom文件,它的作用就是幫我們引入其它jar。

 

得益於starter的作用,使用SpringBoot確實方便,但對剛剛上手SpringBoot的人來說,可能只知道配置屬性是在application.xml或application.yml中添加,但他們各自的屬性都有哪些,具體怎麼配置,卻無從下手。這裏先解決SpringBoot-starter中各屬性的配置問題。

Mybatis的配置是怎麼生效的?查看示例工程的pom依賴:

注意到mybatis-spring-boot-starter幫我們自動依賴了Mybatis所需jar包,其中有一個負責自動配置的mybatis-spring-boot-autoconfigure.jar,緊接着打開此jar,如下:

META-INF/spring-configuration-metadata.json中便是Mybatis在SpringBoot中的所有配置屬性和介紹。

SpringBoot-starter自動配置bean

現在已得知jar包是怎麼樣自動依賴進來,以及他們的配置屬性,那麼接下來該考慮Mybatis所需的bean(如必需的sqlSessionFactory、sqlSessionTemplate等)是如何被自動加載的?

理所應當地,我們繼續去查看mybatis-spring-boot-autoconfigure.jar,注意到裏面有一個自動配置的類MybatisAutoConfiguration:

(1)@Configuration:被掛上@Configuration註解,表明它是一個配置類,作用等同於xml配置,裏面有被@Bean註解的方法,也等同於xml配置的各種。

(2)@ConditionalOnClass/@ConditionalOnBean:自動配置條件註解,用於在某一部分配置中,將另一模塊部分的配置自動加載進來,因為隨着系統越來越大,配置內容越來越多,我們應當將Mybatis的配置放在一處,將log4j的配置放在一處,將SpringBoot自身的配置放在一處,當他們需要互相依賴時,可通過這類註解進行自動配置,如下:

@ConditionalOnClass @ConditionalOnMissingClass
@ConditionalOnBean @ConditionalOnMissingBean
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication @ConditionalOnNotWebApplication
@ConditionalOnExpression
 
@AutoConfigureAfter @AutoConfigureBefore @AutoConfigureOrder(指定順序)
 

(3)@EnableConfigurationProperties:啟用對@ConfigurationProperties註解的bean的支持,這裏對應了配置屬性類MybatisProperties,它裏面定義了Mybatis的所有配置。

(4)@AutoConfigureAfter:應在其他指定的自動配置類之後應用自動配置。即org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration被自動配置后,才會接着自動配置MybatisAutoConfiguration。這裏也解釋了為什麼我們在application.xml中只配置了數據源,而沒有配置Mybatis,但是Mybatis可以正常查庫的原因,就是因為它們配置之間的依賴關係。

到這裏,差不多明白了starter自動配置bean的方式,但是如若再去深究,各種starter的bean是如何被自動加載的,猜想會不會是項目啟動后,SpringBoot自動掃描裏面所有的jar包,再去掃描所有的類,從而將各個bean放置IOC容器中。從結果來看,肯定是SpringBoot在啟動時確確實實地自動加載了數據源和Mybatis相關的bean,不然他們無法正常工作。

回想在我們啟動示例工程時,SpringBoot會自動掃描啟動類所在包下的所有類,而如果還去掃描所有的jar包的話,又是具體怎麼做到的?不妨從入口類調試一把,在SpringApplication.run(DemoApplication.class, args)打斷點,一直追蹤到getSpringFactoriesInstances這塊:

查看SpringFactoriesLoader.loadFactoryNames的方法註釋:

 

使用給定的類加載器從META-INF / spring.factories加載給定類型的工廠實現的完全限定類名。

這裏的spring.factories剛好也存在於mybatis-spring-boot-autoconfigure.jar中,

繼續調試,進入SpringFactoriesLoader.loadFactoryNames,

這裏用類加載器得到工程中所有jar包中的META-INF/spring.factories文件資源,進而通過此文件得到了一些包括自動配置相關的類的集合,有各種工廠類、監聽器、處理器、過濾器、初始化器等等,如下:

最後的org.springframework.boot.autoconfigure.EnableAutoConfiguration集合中當然包括了org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration和org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration。接着必然是將實例化的各個bean放進IOC容器中。

至此我們便明白了SpringBoot是如何自動配置starter裏面的bean的。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

什麼是技術債,為什麼要還技術債?

先說我的結論就是:技術債要還,還不還技術債,決定你所在的公司是不是尊重科學尊重技術,觀點主要有一下三個:

  • 技術債是什麼,對產品和項目有什麼影響
  • 技術債對開發環境和技術氛圍的影響
  • 技術債和技術價值觀

技術棧是什麼,對產品和項目有什麼影響

既然叫技術債,那麼他本質是一種“債”,所以我們先脫離所謂的技術,單獨聊聊什麼是債?債是一個金融上的術語,代表你的負資產,說人話就是代表你欠了別人的錢,在著名美劇《冰與火之歌》裏面的蘭尼斯特家族有一句名言就是:有債必嘗

  1. 那麼生活中有哪些跟債相關的事情呢?我們日常接觸的債有哪些? 花唄,信用卡,透支下個月工資,貸款,高利貸 等等

  2. 債有什麼特點?債本身是一種透支行為,是你犧牲未來滿足自己當下的某種需求,而且所有的債都有一個共同的特點,就是利息,而且跟隨時間~利滾利

  3. 那麼債是怎麼產生的?大家可以想想你什麼時候會用信用卡,用花唄去購物,或者去借高利貸?當你渴望得到某一個東西,但是你本身還不具備購買能力的時候,你會去借債對吧,例如在你財務狀況還很差的情況下,你想買名牌包包,你想買最新款性能最好的蘋果電腦,你想買豪華轎車等等,通過透支未來,來滿足當下的需求,技術債為什麼叫債,就是通過借債,透支系統的擴展性,安全性,來達到快速上線功能目的,借債很容易上癮,為什麼?因為它可以讓你快速滿足慾望(物質,快速變現),嘗到甜頭

  4. 要麼有債要不要還?還債重不重要?:我覺得這其實是看你個人的選擇而已,你借錢也可以不還,可以賴賬,可以能拖一年是一年,甚至也可以忘記你借過的債或者否認它,這可以讓你獲得一些短期利益,讓你嘗到一些甜頭,例如技術上你也可以通過欠債,來快速的實現功能,但是不知道大家是否在意自己的信用和口碑,但在如今的文明社會正在構建就是個人的信用體系,國家徵信中心,支付寶的芝麻信用,微信的支付積分,都是在評價你的個人信用,你的還債的及時和履行契約的能力,最終都是體現在你的個人信用積分上,所以說有債不還也是可以的,這取決與你是否在意你的個人信用和口碑,但如果是一個信用不好的人那麼在一個信用體系如此完善的現代社會裡面是很艱難的,別人不敢跟你做生意,你做什麼時候都必須要先交押金,出行乘坐交通工作,信用好的可以走安全通道,你就必須過安檢和全身掃描,所以在不在債務,還不還債務,其實取決於你想不想做一個講信用的人,做一個用誠信為本去安身立命的人,如果你想做一個誠信為本的人,那麼就要放棄短期利益,把目光放的更加長遠一些,記得我曾經看過一個報道,是講京東創業的故事,京東的企業家劉強東對記者說,如果我們想要賺錢,那麼很簡單,我們有很多捷徑可以走,例如我們不給員工買交社保和五險一金,把大量人員全部轉去外包公司,那麼我們每年營業額馬上就會多十幾個億,可以馬上賺很多的錢,但是他沒有選擇這樣做,這樣通過透支的做事方式確實短期可以獲得一些利益,但是長期來看,你失去的人心,失去了企業的誠信

技術債對開發環境和技術氛圍的影響

產品的迭代就像一個運動員在跑步,汽車在前進,技術債就像運動員消耗的體力,汽車在運行當中所出現的各種問題,沒油,爆胎,熄火等等,還債就是給運動員補水,給汽車加油一樣,是為了可以讓運動員和汽車跑的更遠,不至於因為累積技術債而掛掉,為什麼要重視技術債和細節?因為魔鬼藏在細節當中,再舉幾個和生活息息相關的:

  1. 為什麼我們大樓每天檢修消防和安全設備,為什麼消防要經常做演習?在這些沒有真正產出的事情上耗費精力,難道不能等到真正發生火災發生後去撲滅和搶救嗎 ?
  2. 飛機是在起飛前,為什麼需要做那麼多的安全和檢查措施?確保沒有風險后,然後再執行起飛,難道不能先讓飛機起飛,等到出現問題后再去補救和修復嗎 ?
  3. 為什麼我們提倡每天鍛煉身體,健康飲食?為什麼每年要去醫院體檢?難道不應該等到你的身體已經出現問題,或者發出警報后,你再去看醫生嗎?

說到這裏,技術債的重要性毋庸置疑,重視技術債,就是重視於未然,已最低的成本或者零成本,防止未來的災難發生,還不還技術債很多時候是一種選擇,這些選擇決定了你有沒有預先判斷和解決問題的能力,那麼什麼樣的產品不用還技術債?一次性產品,例如一次性杯子,一次性手套用完就扔掉,所以如果產品長期的可持續的發展,那麼技術債的重要性是毋庸置疑的,對方辯友可能會說我們不是不還技術債,我們只是等做完緊急需求等到空閑時間再還技術債,但是經常做項目的同事應該了解,哪有什麼空閑時間?我們在項目衝刺的時候怎麼可能還會有空閑時間,大部分時間所謂的稍後處理,其實就是不處理,屬於掩耳盜鈴,當技術債被遺忘后就成為項目的定時炸彈埋在那裡了,而且技術債的特性前面也說了,所謂的稍後處理,就是讓它利滾利,拖延時間越長,還債的成本越高,而且人們還債的意願就越低,誰也不敢去碰它,例如,你身體出現問題,你不去看醫院檢查和修復問題,而是一直繼續使用和消耗你的身體,拖到最後實在不能動的,你沒辦法去醫院一查,癌症晚期,那時候神仙也沒救了, 而且技術債不單單是技術債,它就像一個垃圾堆一樣,久而久之不處理,慢慢周圍就會產生更多的垃圾,因此產生的“破窗效應”更加是會對未來的項目環境造成很大的影響,大家也會逐漸喪失維護環境的信心,所以我們在討論技術債的時候不僅僅是討論技術債本身,技術債對團隊追求質量的信心,對大家維護環境整潔的积極性都會造成很大的影響,所以我方觀點是,技術債,有債必嘗,越拖成本越高,最好是在發現的時候馬上處理它,不要讓乾淨的房間出現垃圾堆,只有在乾淨的環境下大家才能持續的高效的去創造,一個需求捏着鼻子做,兩個需求捏着鼻子做,久而久之代碼中就散發出臭味,對於大家的工作體驗和項目質量都會產生巨大的影響,如果連工作都不開心,那還談什麼夢想?沒有良好的技術環境企業就無法吸收和留住高質量的技術人才,人才是現代企業的核心競爭力,沒有人才的企業在瞬息萬變的市場上是難以做出快速反應的

技術債和技術價值觀

不重視技術債就是不重視技術,不尊重科學發展,不能客觀的認識和理解技術的複雜性和軟件工程帶來的價值和意義,我們國家近幾年就因為不重視技術吃了不少虧,比如去年的中興通訊公司被制裁,因為沒有自己的技術,芯片被斷供製裁后卻毫無還手之力,國產目前的大多手機廠商看似繁榮,但手機行業的 8,9 成利潤被都被掌握技術的蘋果公司賺走,打開現在的智能手機裏面你會看到,美國的芯片和谷歌的安卓操作系統,日本的鏡頭和相機模組,三星的屏幕,還要在微薄的利潤上繳納高通的芯片稅,實際上國內大多廠商做的都是代加工和組裝的臟活累活,沒有技術的公司,就會受制於人,不僅賺不到錢,而且公司的命運都是由掌握核心技術的公司決定,再比如一個近期的新聞,哈工大的建模軟件被斷供等等例子,不勝枚舉,那麼技術有多重要?我們就用華為來舉例,華為為什麼是一家值得尊重的科技公司,因為他打破了中國自從第二次工業革命以來,但是因為長期技術落後長期受制於人的客觀事實,中國以前的代號叫做世界工廠,只適合做一些勞動密集型產業,但華為讓中國企業在先進的技術領域,同樣是被美國制裁,為什麼華為活的比中興好很多?因為華為重視技術,從海思芯片到5G 再到操作系統,自己擁有產業供應鏈,有自己的的核心技術,才能掌握自己的命運,而且在取得商業上的成功后,也得到的大家的尊重,相同還有最近處於風口的台灣的芯片製造廠商台積電公司,全球唯二掌握 7納米芯片製造技術的芯片公司,因為自主的核心技術在擁有可以在國際上和英特爾平起平坐資本,綜上所述,不重視技術雖然也可以生存,但是重視技術,掌握核心技術,才能走的更遠,我們都知道技術的目的是要體現商業價值,但前提是要擁有核心技術才配擁有商業價值,沒有技術壁壘的企業和人隨時都可能被人替換,而且幾乎沒有什麼成本,重視技術公司才能發展的更遠,才不會受制於人,才能成為頭部玩家,收割行業90%的利潤,才有可能成為一家偉大並且受人尊重的公司,不然你去想想蘋果公司為什麼不放棄技術,微軟和谷歌為什麼不放棄技術,英特爾和高通為什麼不放棄技術,技術很重要,可以讓個人和企業提升競爭力,不容易被淘汰,對於國家和社會,二次工業革命以來,技術改變了我們的生產效率,從而改變我們社會的運行方式,技術幫助解決了困擾我們幾千年的《馬爾薩斯陷阱》,我們國家經歷過近代史的幾百年技術落後的屈辱后,更加的尤為重視技術,我們在1960 年代大家都吃不飽的情況下我們就研發出自己的原子彈,我們國家級的戰略目標《中國製造 2025》就包含的“芯片,人工智能,區塊鏈,機器人,新能源”等等高精尖產業,目的就是讓我們脫離低端製造業,脫離勞動密集型產業,因為沒有技術含量的重複性的勞動工作未來都將被機器和 人工智能 取代,在未來很難被取代就是人類特有的豐富的想象力和創造力。

最後我想再引用 一個真實的故事,是來源於 NASA 的著名文章《為什麼要探索太空?》,文章的背景是來源於 1970年,贊比亞修女 Mary Jucunda 給 NASA 科學家 Ernst Stuhlinger 博士寫了一封信,信中,Mary Jucunda 修女問道:目前地球上還有這麼多小孩子吃不上飯,他怎麼能捨得為遠在火星的項目花費數十億美元。Ernst Stuhlinger 在回信中寫到一個真實的故事如下:

那是在400年前,德國某小鎮里有一位伯爵。他是個心地善良的人,他將自己收入的一大部分捐給了鎮子上的窮人。這十分令人欽佩,因為中世紀時窮人很多,而且那時經常爆發席捲全國的瘟疫。一天,伯爵碰到了一個奇怪的人,他家中有一個工作台和一個小實驗室,他白天賣力工作,每天晚上的幾小時的時間專心進行研究。他把小玻璃片研磨成鏡片,然後把研磨好的鏡片裝到鏡筒里,用此來觀察細小的物件。伯爵被這個前所未見的可以把東西放大觀察的小發明迷住了。他邀請這個怪人住到了他的城堡里,作為伯爵的門客,此後他可以專心投入所有的時間來研究這些光學器件。然而,鎮子上的人得知伯爵在這麼一個怪人和他那些無用的玩意兒上花費金錢之後,都很生氣。“我們還在受瘟疫的苦,”他們抱怨道,“而他卻為那個閑人和他沒用的愛好亂花錢!”伯爵聽到后不為所動。“我會盡可能地接濟大家,”他表示,“但我會繼續資助這個人和他的工作,我確信終有一天會有回報。”果不其然,他的工作(以及同時期其他人的努力)贏來了豐厚的回報:顯微鏡。顯微鏡的發明給醫學帶來了前所未有的發展,由此展開的研究及其成果,消除了世界上大部分地區肆虐的瘟疫和其他一些傳染性疾病。伯爵為支持這項研究發明所花費的金錢,其最終結果大大減輕了人類所遭受的苦難,這回報遠遠超過單純將這些錢用來救濟那些遭受瘟疫的人。

綜上所述,重視技術債就是重視技術,重視技術就是重視細節和未來,魔鬼存在細節當中,細節決定成敗

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

恕我直言你可能真的不會java第6篇:Stream性能差?不要人云亦云

一、粉絲的反饋

問:stream比for循環慢5倍,用這個是為了啥?
答:互聯網是一個新聞泛濫的時代,三人成虎,以假亂真的事情時候發生。作為一個技術開發者,要自己去動手去做,不要人云亦云。

的確,這位粉絲說的這篇文章我也看過,我就不貼地址了,也沒必要給他帶流量。怎麼說呢?就是一個不懂得測試的、不入流開發工程師做的性能測試,給出了一個危言聳聽的結論。

二、所有性能測試結論都是片面的

性能測試是必要的,但針對性能測試的結果,永遠要持懷疑態度。為什麼這麼說?

  • 性能測試脫離業務場景就是片面的性能測試。你能覆蓋所有的業務場景么?
  • 性能測試脫離硬件環境就是片面的性能測試。你能覆蓋所有的硬件環境么?
  • 性能測試脫離開發人員的知識面就是片面的性能測試。你能覆蓋各種開發人員奇奇怪怪的代碼么?

所以,我從來不相信網上的任何性能測試的文章。凡是我自己的從事的業務場景,我都要在接近生產環境的機器上自己測試一遍。 所有性能測試結論都是片面的,只有你生產環境下的運行結果才是真的。

三、動手測試Stream的性能

3.1.環境

windows10 、16G內存、i7-7700HQ 2.8HZ 、64位操作系統、JDK 1.8.0_171

3.2.測試用例與測試結論

我們在上一節,已經講過:

  • 針對不同的數據結構,Stream流的執行效率是不一樣的
  • 針對不同的數據源,Stream流的執行效率也是不一樣的

所以記住筆者的話:所有性能測試結論都是片面的,你要自己動手做,相信你自己的代碼和你的環境下的測試!我的測試結果僅僅代表我自己的測試用例和測試數據結構!

3.2.1.測試用例一

測試用例:5億個int隨機數,求最小值
測試結論(測試代碼見後文):

  • 使用普通for循環,執行效率是Stream串行流的2倍。也就是說普通for循環性能更好。
  • Stream并行流計算是普通for循環執行效率的4-5倍。
  • Stream并行流計算 > 普通for循環 > Stream串行流計算

3.2.測試用例二

測試用例:長度為10的1000000隨機字符串,求最小值
測試結論(測試代碼見後文):

  • 普通for循環執行效率與Stream串行流不相上下
  • Stream并行流的執行效率遠高於普通for循環
  • Stream并行流計算 > 普通for循環 = Stream串行流計算

3.3.測試用例三

測試用例:10個用戶,每人200個訂單。按用戶統計訂單的總價。
測試結論(測試代碼見後文):

  • Stream并行流的執行效率遠高於普通for循環
  • Stream串行流的執行效率大於等於普通for循環
  • Stream并行流計算 > Stream串行流計算 >= 普通for循環

四、最終測試結論

  • 對於簡單的数字(list-Int)遍歷,普通for循環效率的確比Stream串行流執行效率高(1.5-2.5倍)。但是Stream流可以利用并行執行的方式發揮CPU的多核優勢,因此并行流計算執行效率高於for循環。
  • 對於list-Object類型的數據遍歷,普通for循環和Stream串行流比也沒有任何優勢可言,更不用提Stream并行流計算。

雖然在不同的場景、不同的數據結構、不同的硬件環境下。Stream流與for循環性能測試結果差異較大,甚至發生逆轉。但是總體上而言:

  • Stream并行流計算 >> 普通for循環 ~= Stream串行流計算 (之所以用兩個大於號,你細品)
  • 數據容量越大,Stream流的執行效率越高。
  • Stream并行流計算通常能夠比較好的利用CPU的多核優勢。CPU核心越多,Stream并行流計算效率越高。

stream比for循環慢5倍?也許吧,單核CPU、串行Stream的int類型數據遍歷?我沒試過這種場景,但是我知道這不是應用系統的核心場景。看了十幾篇測試博文,和我的測試結果。我的結論是: 在大多數的核心業務場景下及常用數據結構下,Stream的執行效率比for循環更高。 畢竟我們的業務中通常是實實在在的實體對象,沒事誰總對List<Int>類型進行遍歷?誰的生產服務器是單核?。

五、測試代碼

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>junitperf</artifactId>
    <version>2.0.0</version>
</dependency>

測試用例一:

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.report.impl.HtmlReporter;
import org.junit.jupiter.api.BeforeAll;

import java.util.Arrays;
import java.util.Random;

public class StreamIntTest {

    public static int[] arr;

    @BeforeAll
    public static void init() {
        arr = new int[500000000];  //5億個隨機Int
        randomInt(arr);
    }

    @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class})
    public void testIntFor() {
        minIntFor(arr);
    }

    @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class})
    public void testIntParallelStream() {
        minIntParallelStream(arr);
    }

    @JunitPerfConfig( warmUp = 1000, reporter = {HtmlReporter.class})
    public void testIntStream() {
        minIntStream(arr);
    }

    private int minIntStream(int[] arr) {
        return Arrays.stream(arr).min().getAsInt();
    }

    private int minIntParallelStream(int[] arr) {
        return Arrays.stream(arr).parallel().min().getAsInt();
    }

    private int minIntFor(int[] arr) {
        int min = Integer.MAX_VALUE;
        for (int anArr : arr) {
            if (anArr < min) {
                min = anArr;
            }
        }
        return min;
    }

    private static void randomInt(int[] arr) {
        Random r = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = r.nextInt();
        }
    }
}

測試用例二:

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.report.impl.HtmlReporter;
import org.junit.jupiter.api.BeforeAll;

import java.util.ArrayList;
import java.util.Random;

public class StreamStringTest {

    public static ArrayList<String> list;

    @BeforeAll
    public static void init() {
        list = randomStringList(1000000);
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testMinStringForLoop(){
        String minStr = null;
        boolean first = true;
        for(String str : list){
            if(first){
                first = false;
                minStr = str;
            }
            if(minStr.compareTo(str)>0){
                minStr = str;
            }
        }
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void textMinStringStream(){
        list.stream().min(String::compareTo).get();
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testMinStringParallelStream(){
        list.stream().parallel().min(String::compareTo).get();
    }

    private static ArrayList<String> randomStringList(int listLength){
        ArrayList<String> list = new ArrayList<>(listLength);
        Random rand = new Random();
        int strLength = 10;
        StringBuilder buf = new StringBuilder(strLength);
        for(int i=0; i<listLength; i++){
            buf.delete(0, buf.length());
            for(int j=0; j<strLength; j++){
                buf.append((char)('a'+ rand.nextInt(26)));
            }
            list.add(buf.toString());
        }
        return list;
    }
}

測試用例三:

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.report.impl.HtmlReporter;
import org.junit.jupiter.api.BeforeAll;

import java.util.*;
import java.util.stream.Collectors;

public class StreamObjectTest {

    public static List<Order> orders;

    @BeforeAll
    public static void init() {
        orders = Order.genOrders(10);
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testSumOrderForLoop(){
        Map<String, Double> map = new HashMap<>();
        for(Order od : orders){
            String userName = od.getUserName();
            Double v; 
            if((v=map.get(userName)) != null){
                map.put(userName, v+od.getPrice());
            }else{
                map.put(userName, od.getPrice());
            }
        }

    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testSumOrderStream(){
        orders.stream().collect(
                Collectors.groupingBy(Order::getUserName, 
                        Collectors.summingDouble(Order::getPrice)));
    }

    @JunitPerfConfig(duration = 10000, warmUp = 1000, reporter = {HtmlReporter.class})
    public void testSumOrderParallelStream(){
        orders.parallelStream().collect(
                Collectors.groupingBy(Order::getUserName, 
                        Collectors.summingDouble(Order::getPrice)));
    }
}


class Order{
    private String userName;
    private double price;
    private long timestamp;
    public Order(String userName, double price, long timestamp) {
        this.userName = userName;
        this.price = price;
        this.timestamp = timestamp;
    }
    public String getUserName() {
        return userName;
    }
    public double getPrice() {
        return price;
    }
    public long getTimestamp() {
        return timestamp;
    }

    public static List<Order> genOrders(int listLength){
        ArrayList<Order> list = new ArrayList<>(listLength);
        Random rand = new Random();
        int users = listLength/200;// 200 orders per user
        users = users==0 ? listLength : users;
        ArrayList<String> userNames = new ArrayList<>(users);
        for(int i=0; i<users; i++){
            userNames.add(UUID.randomUUID().toString());
        }
        for(int i=0; i<listLength; i++){
            double price = rand.nextInt(1000);
            String userName = userNames.get(rand.nextInt(users));
            list.add(new Order(userName, price, System.nanoTime()));
        }
        return list;
    }
    @Override
    public String toString(){
        return userName + "::" + price;
    }
}

歡迎關注我的博客,裏面有很多精品合集

  • 本文轉載註明出處(必須帶連接,不能只轉文字):字母哥博客。

覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出了如下的精品內容,期待您的關注。

  • 《手摸手教你學Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2一本通》
  • 《實戰前後端分離RBAC權限管理系統》
  • 《實戰SpringCloud微服務從青銅到王者》
  • 《VUE深入淺出系列》

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?

【代碼修鍊系列分享】改掉這些壞習慣,還怕寫不出健壯的代碼?(一)

Code Review 是一場苦澀但有意思的修行。

近期對團隊負責的項目,進行了一次 Code Review,代碼評審過程中遇到的那些編碼壞習慣,笑的合不攏嘴。不過,評審中很多代碼編寫問題,以往都多次提及過,所以還是按奈不住心中怒氣的小火苗。

作為用代碼編寫人生的程序員,能擁有寫一手健壯代碼的本領,那絕對很有必要。因為健壯的代碼能夠把 Bug 扼殺在搖籃里,能夠讓問題止步於上線前。

那麼,怎樣才能練就寫出健壯代碼的本領呢?

本次着重談談那些代碼編寫時的一些壞習慣,改掉這些壞習慣,相信會向健壯代碼邁進一大步。

一、編碼時易忽略性能的壞習慣 

壞習慣一:調用低效的構造器,創建包裝類型的對象。

反例:

正解:

解惑:使用 Long.valueOf(long) 代替 new Long(long),可以提高性能。

如 Long 源碼所示,如果當傳入的值介於 -128~127 時,會優先從緩存中返回緩存的值,而不是進行 new,充分利用空間換取時間,所以當值介於 -128~127 時,採取 Long.valueOf(long) 的效率要比 new Long(long) 快很多。

建議:

  • 凡是涉及到 Long, Integer, Short, Character 以及 Byte 創建對象時,優先採用高效的 valueOf() 方法,而不是直接用低效構造器創建實例。
  • 享元設計模式在這兒用到了,什麼是享元模式?(留個作業)

壞習慣二:使用 keySet 迭代器迭代 Map,獲取對應的 value。

反例:

正解:

解惑:keySet 方式遍歷 Map 的性能不如 entrySet 性能好。

如果採用 keySet 的方式獲取 Map 中 key,然後通過 key 獲取 Map 對應的 value,如上圖 HashMap 源碼所示,每次都需要通過 key 去計算對應的 hash 值,然後再通過 hash 值獲取對應的 value,效率會低不少。

建議:

  • 如果想獲取 Map 對應的 key 和 value,則推薦使用 entrySet。
  • 如果只是單純獲取 Map 對應的 key,則推薦使用 keySet。

壞習慣三:使用 new Date().getTime() 獲取當前時間戳。

反例:

正解:

解惑:如下圖 Date 源碼所示,Date 構造方法中最終還是調用了 System.currentTimeMillis() 方法來獲取時間戳。

建議:

  • 獲取當前毫秒數採用 System.currentTimeMillis(),而不是new Date().getTime(); 
  • 獲取更加精確的納秒級時間值,採用 System.nanoTime;
  • 在 JDK8 中,針對統計時間等場景,建議使用 Instant 類。

壞習慣四:循環中使用 ”+“ 號拼接字符串。

反例:

正解:推薦使用 StringBuilder/StringBuffer 進行字符串拼接。

解惑:「Java 程序該怎麼優化?技巧篇」以前的這篇分享做過試驗,本次不贅述。

二、編碼時易犯的一些小毛病 

毛病一:變量作為 equals() 方法的調用方。

反例:

正解:

解惑:totalCount 應該作為方法  equals() 的調用方,而不是參數 作為調用方,因為參數作為調用方會出現空指針異常。

建議:

  • 字符串的比較,常量建議當做 equals() 方法的調用方;
  • 字符串判斷空,建議用項目中的工具類。

毛病二:對象為 null 的檢查滯后。

反例:

正解:請在使用 data 對象前,做好是否為 null 的判斷。

解惑:後置對象為空的檢查,可能會導致空指針異常的發生。

毛病三:要求傳入非空的方法,傳入空值。

反例:

正解:signInfo 變量的值可能存在為空的情形,導致發生空指針異常。

建議:發生異常的時候,方法該終止就終止;盡量做好防禦性編程,該校驗的參數進行必要的校驗。

三、寄語寫最後 

常在河邊站哪有不濕鞋,再牛逼的碼農,編碼也會有失誤的時候,很有必要藉助一款代碼檢查工具,做最後一道防線。

在這裏,推薦 FindBugs、Checkstyle、SonarQube 三款代碼檢查工具,不過我用的最多的當屬 FindBugs,可以拿去一試,使用門檻幾乎為零。

好了,編碼中易犯的那些臭毛病,本次就談到這裏,不知道有多少條是觸動了你的心弦,希望有則改之。

關注同名公眾號:一猿小講,回復「1024」可以獲取精心為您準備的職場打怪進階資料。

一起聊技術、談業務、噴架構,少走彎路,不踩大坑,會持續輸出原創精彩分享,敬請期待!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

【故障公告】阿里雲 RDS 實例 CPU 100% 故障引發全站無法正常訪問

非常抱歉,今天凌晨 3:20~8:30 左右,我們使用的阿里雲 RDS 實例 SQL Server 2016 標準版突然出現 CPU 100% 故障,造成全站無法正常訪問,由此給您帶來巨大的麻煩,請您諒解。

問題很奇怪,故障期間是數據庫服務器負載極低的時間段。從阿里雲 RDS 控制台 CloudDBA 看,故障期間下面的一個 SQL 語句大量執行,並且極其消耗 CPU 。

開始我們以為是這個 SQL 語句引發的故障,但排查下來這個 SQL 語句本身並沒有性能問題,而且已經使用了至少6個月。

最終恢復正常是通過 RDS 的2次主備切換,當發現故障后,我們立即進行主備切換,但切換后 CPU 依然 100% ,然後我們排查 SQL 語句的問題,排查未果,然後又進行一次主備切換,才恢復正常。

事後分析后發現應該是第一次主備切換沒有成功完成,阿里雲 RDS 控制台查看不到主備切換日誌,但2次切換,只有第2次收到郵件通知,由此可以推斷。

您的雲數據庫RDS實例:xxx(名稱:enable or disable task fetching while rds2slb transgfer.)任務觸發切換完畢,請檢查程序連接是否正常,建議設置自動重連機制以避免切換影響。

問題的原因有待進一個分析,再次抱歉由此給您帶來的麻煩。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

《T-GCN: A Temporal Graph Convolutional Network for Traffic Prediction》 論文解讀

論文鏈接:https://arxiv.org/abs/1811.05320

最近發現博客好像會被CSDN和一些奇怪的野雞網站爬下來?看見有人跟爬蟲機器人單方面討論問題我也蠻無奈的。總之原作者Missouter,博客鏈接https://www.cnblogs.com/missouter/,歡迎交流。

整理、精鍊了一下這篇論文的思路。

Abstract:

交通預測的難點在於交通拓撲網絡複雜的結構與隨時間動態發生的交通變化;為了提取交通網的空間與時間特徵,文章提出了一種時間性的圖卷積網絡模型,結合了門級循環單元(GRU)與圖卷積網絡(GCN)。其中圖卷積網絡被用於提取複雜拓撲結構中的空間性信息,而門級循環單元則為了提取時間關係,被用於學習交通數據中的動態數據。

Introduction:

交通預測過程:分析交通道路狀況,包含流量、速度、密度;挖掘交通模式,同時對道路上的交通狀況進行預測。

預測結果:交通管理者預測擁堵狀況、限制交通工具的科學基礎、出行者效率選擇出行工具、路線的保障。

難點:

1、 空間關係:交通流的變化被拓撲結構的城市交通網主導,上游的交通狀態通過傳輸作用影響下游的交通狀態,而下游交通狀態通過反饋作用再影響上游交通。

2、 時間關係:交通流隨時間動態變化,主要表現在周期性和趨勢上;現有的交通狀況被前一刻的交通狀況影響。

現存交通預測方法缺陷:一些交通預測方法(ARIMA、Kalman filtering model,etc)只關注了交通狀況的動態變化而忽視了空間關係,導致交通狀態的變化不被道路網約束,同時一些模型嘗試使用卷積神經網絡進行空間性建模,但這些模型一般只使用於歐幾里得類型的數據(規則矩陣、圖像等),無法在拓撲結構的城市交通網絡中運作。

T-GCN貢獻:

1、 結合了GCN與GRU,內容與abstract重複,不做多提。

2、 T-GCN的預測結果展示了一個不同視角下的穩定狀態,表示T-GCN除了預測短周期的變化,還能預測長周期的變化。

3、 我們使用兩個現實的數據集評估模型,相較其他預測模型,減少了1.5%~57.8%的預測錯誤率。

Related work:

交通預測方法分類:模型驅動的方法、數據驅動的方法;

模型驅動的方法:解釋即時、穩定的交通關係如交通流量、速度與密度,需要複雜細緻的系統建模與巨大的算力,且由於諸多因素的影響,現實環境中交通數據的多樣性無法被精確描繪。

數據驅動的方法:基於數據統計所得規律推斷交通狀況的變化。不分析物理屬性與交通系統的動態變化有着較高的複雜度。其中的historical average model不需要假設、計算過程簡單,但精確度不佳。

擁有更高精確度的模型被提出,分為兩種:含參數的與非參數的。

含參模型假定回歸函數,參數在對原始數據的處理過程中確定。傳統含參的模型是在系統模型為靜態的假設基礎上建立的,反映不了交通系統的非線性與不確定性,也克服不了交通事故等突發隨機事件的困難。不含參數的模型只需要足夠的歷史數據就能自動學習靜態規律特徵,但先前形如LSTM、GRU的模型僅僅考慮了時間關係而忽略了空間關係,不能精確預測道路上的交通信息,如何充分利用空間信息成了交通預測的關鍵,而利用CNN進行空間關係提取的模型雖然在交通預測上取得了顯著進步,但無法應用於複雜拓撲結構的城市交通網,隨着GCN研究的深入,拓撲結構空間特徵的提取問題也得到解決。

(這段論文寫的有點長…堆了一堆文字讀的我有點難受)

Methodology:

問題定義:根據歷史數據預測某一特定時間段的交通信息,交通數據通常被定義為速度、密集程度、交通流。使實驗不失普遍性,在實驗章節使用交通速度作為交通數據的代表。(Without loss of generality, we use traffic speed as an example of traffic information in experiment section.這句語感有點僵了)

定義:設定無權圖G=(V, E),V、E分別代表道路點與邊,N為道路的數量,設定鄰接N*N矩陣A表達道路與道路之間的聯繫;設定N*P特徵矩陣X,P代表點屬性特徵的數量,即歷史時間序列的長度,使用N*i矩陣 表示在時刻i,每條道路上的速度,屬性特徵也可以是交通速度、交通流等屬性。

問題轉化:交通空間-時間性預測被轉化為學習以拓撲圖G為前置與特徵矩陣X的映射函數,計算得到在下T時刻的交通信息:

過程概覽:首先以長度為n的歷史時間序列數據作為輸入,使用GCN接收拓撲結構的空間信息,其次將接收到的空間、時間信息輸入GRU當中,獲取各個單元間的動態信息變化,以提取時間性的特徵,最後在全連接層獲得結果。

空間關係建模:利用GCN提取圖結構的數據,通過給定的鄰接矩陣A、特徵矩陣X,GCN在圖上通過提取相鄰結點特徵構建傅里恭弘=叶 恭弘域,使用堆疊的卷積網絡,表示為:

Â為A與單位矩陣I相加所得, D為度矩陣, Hl為第l層的輸出, θl包含該層的參數, σ代表非線性回歸的激活函數。(我懷疑論文這裏的上標打錯了)

兩層GCN模型可被表示為:

其中 ,P*H的 矩陣代表從輸入到隱藏層的權重,P為特徵矩陣的長度,H為隱藏單元的數量;H*T的W1代表從隱藏層到輸出層的權重, f(X,A)∈RN*T代表長度為T的預測輸出,ReLU()作為修正線性單元,作激活層用。

時間關係建模:被廣泛應用的循環神經網絡因梯度消失/爆炸的原因,不適用於長周期的預測;LSTM與GRU作為循環神經網絡的變種,克服了上述問題。其共同原理都是利用門級機制儲存盡可能長的周期信息;LSTM因其複雜的結構,GRU結構更加簡單,故計算時間更短。

 

圖中ht-1表示t-1時刻的隱藏狀態, xt表示t時刻的交通信息, rt代表重置門,用於控制先前時刻狀態信息的度量; ut為上傳門,用於控制上傳到下一狀態的信息度量; ct為t時刻時儲存的信息, ht為t時刻的輸出狀態;總的來說,GRU通過獲取t-1時刻的隱藏狀態與當時的交通狀態信息得到t時刻的交通信息。

T-GCN:

 

T-GCN的結構如圖,右側為T-GCN的處理單元: 為t-1時刻的輸出,GC為圖卷積過程,ut 、 rt分別為上傳門與重置門, 為t時刻的輸出。具體計算過程為:

f(A,X)代表前文定義的GCN計算過程,w與b代表訓練過程中的權重與偏移量。(很大部分照搬了GNU的公式)

損失函數:

目標:最小化真實交通速度與預測交通速度的誤差。Y分別代表真實速度與預測速度,損失函數如下:

其中 λLreg用於防止過擬合。

Experiments:

選取數據集:

1、SZ-taxi:數據分為兩部分,156*156的鄰接矩陣表示路與路之間的空間關係,描述每條路上隨時間變化的特徵矩陣。

2、Losloop:由鄰接矩陣與特徵矩陣組成,鄰接矩陣由交通網絡中的傳感器計算;同時作者對數據集中的殘缺部分使用線性填充的方法進行了補全。

輸入的數據全部進行了歸一化處理,80%的數據用於訓練,而20%的數據被用於測試。實驗對接下來15、30、45、60分鐘的交通速度進行預測。

評價指標:

文章列出了五個用於評價T-GCN預測表現的指標:

1、均方根誤差:

2、平均絕對誤差:

3、準確率:

4、 確定係數:

5、可釋方差值:

其中yj’i分別代表第j次時間、第i條路的真實交通信息與預測信息,M為時間樣本的數量,N為路的數量,Y分別代表 與 的集合, 帶上劃線的Y為Y的平均數。

R2與var用於計算相關係數,衡量預測結果表示實際數據的能力,數值越大則預測能力越優越。

選取模型參數:

超參數:包括學習率(0.001)、抓取數量(32)、訓練輪數(5000)、隱藏單元數量(通過多次實驗取最優預測效果)

針對SZ-taxi文章選取[8,16,32,64,100,128],分析預測準確率的變化,得到不同隱藏單元數量下RASE與MAE、Accuracy、R2 、var的值如圖:

 

顯然數量為100時效果是最好的(真有這麼巧的事情嘛…)。隱藏單元超過一定數量性能下降的原因在於數據單元超過一定值後計算複雜度增加,且訓練數據會出現過擬合現象。

實驗結果:

將T-GCN預測效果與baseline對比,包括HA、ARIMA、SVR、GCN、GRU,所得實驗數據如下:

 

高預測精準度:門級循環網絡的預測精度顯著高於其他baseline算法,HA、ARIMA、SVR等算法因難以處理複雜、非固定的時間數據而預測效果不佳,GCN預測效果不佳的原因僅僅在於僅考慮了空間特徵而忽略了交通數據是一個典型的時間序列數據這一事實。

ARIMA比HA檢測效果弱的原因在於ARIMA不適用於長周期的檢測,且計算每個節點誤差的方式導致一些數據中的波動會導致最終的計算錯誤。

時空預測能力:為了檢驗模型是否能夠從交通數據中提取時空特徵,文章將模型與GCN、GNU模型進行了比較:

長周期預測能力:在不同的時間範圍(文章只寫了“horizon”,根據前後文認定為是時間範圍)下,T-GCN都能獲得最好的預測效果且預測結果擁有較小的變化趨勢,證明了T-GCN擁有更好的長周期預測能力;文章以T-GCN在不同時間點的結果作為論證:

 

干擾分析與魯棒性:通過向數據中添加兩種不同的噪聲檢驗T-GCN的魯棒性,高斯分佈、泊松分佈的 值作為自變量被改變,分別添加到兩種數據集上,得到結果:

 

由評估指標的隨噪聲的變化細微可以得出T-GCN具強魯棒性的結論。

模型解釋:

文章將T-GCN所得的預測結果與真實數據可視化得到結論:

 

模型對於峰谷值的預測效果不佳,原因在於T-GCN在傅里恭弘=叶 恭弘域中定義了平滑過濾器,通過不斷移動過濾器提取空間特徵,造成了全局預測中的細微變化,使得曲線中的峰變得平滑。

文章還指出預測與實際之間存在固定誤差,由數據集的特殊性造成,即SZ-taxi數據集表示某時刻出租車的數量可能為0,但實際道路上車輛的數量不一定為0;

對這篇論文的解讀就到這裏結束了,Methodology部分使用GCN與GNU的理論,設計了新的計算單元;Experiment部分很讓我受教,對實驗的條件、前提設定的非常詳盡,在介紹數據集與衡量指標后,對選取實驗參數作了嚴格的實驗論證;對實驗結果進行了詳盡的分析,通過與其他幾個模型的預測結果進行對比,從空間、時間、時間跨度預測、精度、魯棒性等角度對模型的優越性進行對比論證,數據的選取與展示都精確地契合了論證的論點;最後關於傅里恭弘=叶 恭弘與峰谷偏差的模型解釋很精妙。

關於GNU、LSTM的學習解讀會繼續跟進。同時也會對這篇論文git上的開源代碼進行解讀與實驗復現。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

重構下載功能模塊

背景

最近項目新上線的版本中,出現了很多涉及下載相關的bug;經過艱難的代碼調試排查,可還是沒有準確定位問題。主要還是由於代碼年久,經過多代人的修修補補,到處都是“壞味道”的代碼。跟項目經理溝通過後,同意重構這部分的代碼。下面就簡單記錄一下重構的過程。

項目現狀

項目最早可追溯至2014~2015年,分為配置管理網站(Server),WPF桌面軟件(Client)。桌面軟件又分為:用戶操作界面WPF,後台服務 Windows Services 程序。
在後端Services中,維護一個本地的小型Firebird數據庫,為WPF提供數據和用戶狀態保持;實現了從遠程服務器同步數據到本地,訪問遠程接口,下載管理,數據上報等功能。而我這次要做的就是,重寫下載管理。下面是關於舊代碼的分析:

  1. 三種不同的下載觸發機制:軟件啟動觸發、用戶觸發,數據同步到本地觸發;
  2. 有八種不同的資源下載,分別在不同的表中管理;
  3. 有五套複製粘貼的代碼:軟件啟動(兩套)、用戶觸發(兩套)、數據同步(一套);
  4. 大量無意義嘗試,比如下載失敗404后,短時間內沒有必要再次嘗試;
  5. 狀態管理不統一,有的下載完成狀態改為 ReadyForUse,有的下載完成狀態改為 DownloadSuccess;
  6. 執行方法語義重疊,比如 DownloadPause 和 DownloadStop,DownloadFinished 和 DownloadSuccess;
  7. 大段註釋代碼,這些代碼基本永遠不會再使用的;

重構設計

鑒於項目是在運行階段,一方面要考慮時間成本,另一方面要保證原有的運行方式。在當前軟件的框架下,把重寫的代碼限定在下載模塊內部,對外的接口不做改變。
重構代碼的抽象和設計,也是依據當前項目的實際情況,盡可能的通用和易擴展。設計的UML類圖如下:

下面的三個虛類,是下載管理流程的核心,所有的控制邏輯都包含在其中。

  1. DownloadResourceAbstract 虛類 資源文件的基本信息: DatabaseID 和 ResourceID為了兼容不同數據庫表的設計;DownloadPriority 預設優先級;DownloadImmediatelyPriority 用戶觸發的下載,優先級最高,立即執行;其它字段涵義可見字段名稱;
  2. DownloadWorkItemAbstract 虛類 資源下載操作類,包含下載狀態,開始,停止,MD5檢查,狀態更改的回調方法;與①一對一關係;
  3. DownloadControlerAbstract 虛類 控制同時下載的數量,根據優先級控制下載的順序;與②一對多關係

下面的類,是具體下載方法的實現;當前的項目只有HTTP下載,類圖中也只實現了HTTP的下載的管理功能:

  • 可擴展下載方法設計:FtpClient、HttpClient繼承自DownloadClientAbstract;
  • 關聯 HTTP 下載,分別實現的子類 HttpDownloadWorkItem 和 HttpDownloadControler;

對不同類型的資源文件,組合不同的下載方式:

  • AutoHttpDownloadDealer: 自動下載的資源 + HTTP 下載;
  • UserOperHttpDownloadDealer: 用戶手動操作的資源 + HTTP 下載;
  • 由數據同步到本地的觸發下載資源 + HTTP下載;(未在UML圖中畫出)

發現bug的真實原因

在重構測試階段,意外發現了bug的原因:前段時間更換了文件服務器,而新的文件服務器,不支持斷點續傳,HTTP Status 返回的不是預期的Partial Content(206),而是OK(200);下載文件不存在時,HTTP Status 返回的也不是 404,而返回自定義的 Response Text 。。。

由於這兩個不合理的地方,導致軟件的下載功能,出了好多莫名其妙的bug,再疊加到處複製 + 粘貼“壞味道”的代碼,修復起來異常繁瑣,於是就有了重構這件事情。

個人感受

在當前的項目中,也做了幾次小範圍的重構,要麼代碼影響範圍小,要麼只是在原代碼基礎上套個框架。而這次是徹底幹掉原代碼,重新設計,重新寫。下面是代碼重寫完成后 git merge 的 log:

Showing 1107 revision(s), from revision 6092a531 to revision f336c077 – 1 revision(s) selected, 166 file(s) selected; line: 5226(+) 5251(-) files: modified = 118 added = 28 deleted = 20 replaced = 0

從上面的log匯總信息,好像也不足以展示修改工作量。這些修改大約花費了我一周的時間,自願工作日加班,自願周末加班(有時候代碼寫上頭了,還得強迫自己下班休息去)。開始的前三天的時間,邊讀舊代碼,邊搭建新的框架,嘗試把舊代碼融入到新設計中;後期轉換思路,理解代碼邏輯,把代碼邏輯融入到新設計中。

這樣就可以放開手腳的干起來了,寫代碼的時候,感覺時間過的好快,如有神助般各種代碼中的細節,也會不假思索的寫出來。在下階段單元測試中,非常順滑,基本沒有發現什麼bug,真的是酣暢淋漓。

最最讓我寒心的是,好不容易重構測試完代碼了,壓抑着無比激動的心情,希望組裡的同事給個积極肯定的反饋,可連一個“卧槽”也沒有,就行往常平淡的工作日。。。項目經理也是很淡然的說,要儘快拿給測試。

尾聲

即使我的努力和心血沒有得到,預期中的肯定,我也要把這個過程留存記錄下來:把重構的代碼剔除項目信息,再提取合併通用的部分,重新梳理成一個類庫Github 地址;寫一篇文章來記錄一下。

其實,後面我細細回想了一下。如果最開始項目設計的下載功能是,把所有下載資源放在同一張數據庫表中管理,是不是就那不就更簡單了?如果最最早期的設計做好了,後期可以省掉多少功能擴展、修復bug、重構。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

奧迪看衰純電動車市場 新款車型延後推出

 

隨著寶馬等公司逐漸擴大投入純電動車市場,奧迪並未選擇加速緊追,相反的,奧迪並不看好純電動車市場的發展。

近日歐洲媒體 Worldcarfuns 報導,奧迪公司並不想花費大量的時間和金錢來推出出色的電動車型,來與寶馬、特斯拉等品牌的電動車競爭。

根據奧迪的純電動車產品規劃,其曾計劃推出的 R8 電動版、Q6 電動版等 4 款新純電動車,量產時間都將推遲延後。對此,奧迪董事會成員兼銷售總監 Luca de Meo 表示,奧迪對純電動車的前景並不看好,因此暫時沒有生產純電動車的計劃。

 

(圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?