標籤: 網站設計

  • 豐田奕澤怎麼樣?讓它的設計師來解答這個問題吧

    豐田奕澤怎麼樣?讓它的設計師來解答這個問題吧

    具體的策略,用我的概來概括就是“非常6+1”,六個策略+一個特別關注的事情,具體分為品牌策略、車型策略、網絡策略、區域策略、經銷商盈利策略,一個就是跟經銷店溝通支持,提供快速解決。通過非常6+1的落實,Q1結果出來,銷售了16萬,加上關閉了的4款車型,去年同比增長11%,應該說順利實現開門紅。

    如果你要問我一汽豐田近期最受關注的一款車是什麼,我絕對會毫不猶豫告訴你——奕澤,作為一汽豐田旗下首款小型SUV,奕澤憑藉設計犀利的造型、雙色的車身等諸多亮點吸引了不少人的關注,而這一次北京車展上奕澤也正式亮相,雖然並沒有上市,但是距離奕澤馳騁在中國大街小巷那一天已經比較近了,而這一次北京車展我們有幸採訪到一汽豐田汽車銷售有限公司的田青久先生以及一汽豐田銷售常務副總經理水谷雅史先生,一起看看他們能夠給我們分享哪些關於奕澤以及一汽豐田的秘密吧!

    主題:一汽豐田專訪

    時間:2018年4月25日下午2:30

    地點:中國國際會展中心E1

    受訪人:一汽豐田汽車銷售有限公司 田青久先生

    一汽豐田銷售常務副總經理水谷雅史先生

    一汽豐田銷售常務副總經理水谷雅史先生

    提問:一汽豐田的各位領導好,我想請問一下炫酷的奕澤6月份上市,有哪些亮點抓住用戶呢?

    田青久:他的亮點很多:首先,在基礎的駕駛性能上,無論是駕趣、拐彎、剎車技術性,均達到世界領先的水平。前期在珠海,我們經銷商進行的對比試駕活動,我也參与了試駕,確實有着改朝換代的感覺,跟其他的SUV完全不同,我們將儘快的安排在座的媒體老師體驗這款車。

    說起來亮點幾大方面:第一,奕動美學的設計,顏值即正義,顏值用太多的話無法說清楚,只有大家真正感受,用我的話就是一見傾心,心動不已;二見鍾情,買它回家。中看不中用也不行,是吧?首先,鑽石動力組合,搭載了Dynamic Force Engine 2.0L “噴汽流控發動機”加上10速變動器。為什麼是鑽石動力組合,它的性能達到了非常高的水平,126千瓦,熱效率達到世界領先40%。這是從中用的角度來說。中看中用之後,安全不安全呢?在安全配置上從起步車型開始,全系搭載了豐田智行安全系統(TSS系統)和10氣囊,媒體老師都很了解,這種配置一般只在豪華車型上會配備。所以,概括來說就是前所未有的顏值,前所未有的駕趣,前所未有的安全。

    提問:伴隨着消費升級,一汽豐田2018年會進行怎麼樣的調整,來應對中國汽車市場的變化?

    水谷雅史:首先感謝您對一汽豐田的關心,感謝您的提問。接下來我來回答一下您的問題。

    首先,中國市場在飛速的變化發展,這是我的認知。通過這一次的車展,我們看到新的國產車不斷出現,以及新的品牌不斷出現,新的市場在充實。同時,我們也感覺危機感。所以,我想未來的汽車市場外資品牌與純國資品牌的競爭會日趨激烈,這是毋庸置疑的。所以,在這樣的競爭環境下,各大企業必須要提升自己商品的魅力與實力才可以。

    為此,從今年開始我們開始導入了TNGA豐巢概念下的新車型。昨天大家看到奕澤IZOA這款車型,在外觀、環境貢獻能力、安全都有進化和提升,商品大幅進化,就是激烈的市場,帶給我們的價值。

    第二,我們經銷店給我們客戶提供什麼樣的服務,在未來是越來越重要的。未來,我們將吸取海外的服務經驗,將它們引進國內,給客戶提供更好的服務。謝謝您的問題。

    提問:我想問田總一個問題,大家都關注奕澤的問題,我想問一下銷量的問題,2018年銷量目標定位69.5萬台,目標設定是基於什麼樣的考慮,今年將採取什麼樣的措施來確保目標的完成?

    田青久:我們考慮了幾個因素:

    第一,外部環境。媒體老師都知道,中國車市進入穩定低速增長狀態,前些年動輒二位數高速增長時代一去不復返。

    第二,內部因素。一汽豐田正處於發展調整期,今年有四款車型退市,奕澤下半年才上市量銷,有拉伸的過程。今年的增量,需要我們通過現有車型營銷努力,提高營銷質量來解決。

    那麼我們在制訂目標的時候,不局限於這個目標,而是要挑戰71,乃至於更高,具體涉及到打法、策略的問題。總體策略是12個字:“增量為本,節奏為先,結構為王”,找增量出口,這是本源。節奏上半年贏,全年贏,把車型銷售作為調整,有明星車型。具體的策略,用我的概來概括就是“非常6+1”,六個策略+一個特別關注的事情,具體分為品牌策略、車型策略、網絡策略、區域策略、經銷商盈利策略,一個就是跟經銷店溝通支持,提供快速解決。通過非常6+1的落實,Q1結果出來,銷售了16萬,加上關閉了的4款車型,去年同比增長11%,應該說順利實現開門紅。我相信後幾個季度堅定執行策略,很好的超額完成,在69.5萬基礎上的目標。

    提問:我想問水谷雅史先生一個問題,上午一汽豐田中國發布會公布了卡羅拉雙擎E+的上市會,你能否介紹一下這款車以及戰略意義?

    水谷雅史:感謝您的提問。今天上午剛剛公布了卡羅拉雙擎E+這款車型,我認為這款車型的戰略意義,未來面向新能源需求的1號車,具體會在2019年正式進行導入。

    我認為這款卡羅拉車型,是目前為止豐田在全球銷售的混合動力的進化版、升級版。大家可能都知道,豐田電動化車型在全世界銷售了100多個國家,銷售量達到1100萬台以上。那麼這一次,在原有車型基礎上,進一步技術能力出現了插電式混合動力卡羅拉雙擎E+的這款車型。這款車型未來面對中國能源政策,是一款毫無問題的車型,而且在充電續航能力上,即使沒有油電支持下,只有純電動的情況下,也可以行駛相當長距離。同時大家也知道,卡羅拉這款車型長期受到全球歡迎,結合上新能源技術,強強聯合出來的車型。

    我們會好好準備,把這樣的好產品奉獻給中國市場。這裏我再做一個預告,2020年作為新能源政策的對應第二號車型,是EV車型。再跟大家預告一下,這款車型將成為一汽豐田在全球導入第一款奕澤的EV車型,中國是先於全世界的任何一個國家。

    提問:移動互聯網增長迅猛,應對新時代變革方面,一汽豐田在数字營銷、粉絲營銷方面,有沒有什麼創新的想法?

    田青久:這個問題我來回答,一汽豐田董事長特別提倡營銷創新,有一句話創新到不能再創新。那麼一汽豐田的創新突破點在哪?最後選在数字體驗營銷方面。為什麼選擇這個端口呢?根據統計目前汽車市場消費者75%是80、90后,而這部分客戶從小接觸互聯網,是互聯網的原住民。在中國消費市場上,移動互聯網應用越來越廣泛,所以我們把創新的突破點鎖定在這個窗口上。

    具體正在嘗試做兩方面的工作,一是我們開發了数字聯合運營平台,流量聚合,全過程進行可視化管理,支持渠道(經銷商)DCC業務,提高信息量。第二方面打造粉絲營銷矩陣,600萬保有客戶、620家經銷家、3000零件供應商的現有龐大基盤、加上以在座各位為代表的四五百家友好的媒體、廣大的員工,這五個維度加在一起,有好內容產生的話,在粉絲營銷矩陣上一次觸達接近2000萬人群,二次裂變就可以覆蓋上億的人群。

    當今時代人人都是自媒體,就是媒體平台,傳播效率不言而喻。同時建立粉絲社群,通過跟粉絲互動,及時了解粉絲需求的效果,進而通過蓄水和放水的功能,實現銷售的轉化。假設按照0.5%轉化率來算,我們有200萬的粉絲,就是有一萬台增量。所以,在這方面积極探索。目前來看是效果是非常好的。今後大家有好主意,歡迎积極跟我說一下,吸收大家的智慧,我們一起來做嘗試。

    提問:我想問田總一個問題,去年600萬達成,一汽豐田推出“安享管家”計劃。能否從客戶利好的角度,給我們介紹具體的內容?

    田青久:營銷2.0時代汽車銷售與服務之外,確實各個品牌都在研究汽車延伸價值鏈的計劃。我們“安享計劃”,是把客戶在購車、用車過程當中的痛點都覆蓋到,具體安享計劃有八個方面,包括安心二手車、純牌零件、純正精品、安心租車、AAA延保、AAA保險、貼心金融等。只要用戶購車、用車的過程當中有困難,我們都有相應的產品服務來對應到他們。

    謝謝。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

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

  • 跑得不夠快,配置不夠高,但TA的魅力依然擋不住

    跑得不夠快,配置不夠高,但TA的魅力依然擋不住

    聽瑪莎拉蒂堅持與寶華韋健合作隨車打造的音響系統可以帶給你在聽覺上殿堂級的享受,甚至可以調整側重地方,比如往後排照顧,就可以向後排調節,能輕易分出前排後排的區別。最神奇的是,經過無數次調校之後,發動機艙傳來的聲浪並不會影響音響效果,甚至會相互加成,帶給你獨特的聽覺享受。

    瑪莎拉蒂,一個最喜愛的超豪華品牌,沒有之一。在有的人眼裡,瑪莎拉蒂是個跑車裡的異類,沒有讓人驚艷的百公里加速成績,沒有讓人眼前一亮的高科技配置,更沒有跑車具有的戰鬥姿態,但是,可以告訴你,瑪莎拉蒂具有的是其他品牌所沒有的一種浪漫,把豪華、運動、享受都融合在一起的意式浪漫。

    在這次北京車展專門跑去瑪莎拉蒂展台個性化配置專區感受一番這種浪漫情懷,並通過看、聽、聞、觸、味全方位體驗。



    看瑪莎拉蒂全系車型就是一種享受,造型不僅獨特個性,且在不經意間會發現瑪莎拉蒂融入車裡的品牌造型,比如,你會發現在輪轂的形狀就是圍繞瑪莎拉蒂的標誌(海神三叉戟)而設計。並且全系車型都接受定製,從車身顏色、車漆種類、輪轂、制動卡鉗到內飾材料、多功能方向盤、豪華還是運動座椅、座椅面料等等,無不體現屬於自己的個性訂製。



    瑪莎拉蒂堅持與寶華韋健合作隨車打造的音響系統可以帶給你在聽覺上殿堂級的享受,甚至可以調整側重地方,比如往後排照顧,就可以向後排調節,能輕易分出前排後排的區別。最神奇的是,經過無數次調校之後,發動機艙傳來的聲浪並不會影響音響效果,甚至會相互加成,帶給你獨特的聽覺享受。



    意大利頂級皮革帶給車內獨特的芳香,讓駕駛者更覺舒適,展台專門聘請的咖啡師調出香濃的意式咖啡,帶來極致的享受。



    意大利頂級皮革以及精緻的手工縫製,無一不在體現瑪莎拉蒂在工藝方面的水平以及造車的誠意。



    最後,在瑪莎拉蒂個性化配置專區還提供了頂級廚師烹飪的意大利美食,開啟味覺享受的同時也結束了本次瑪莎拉蒂的體驗之旅。

    瑪莎拉蒂,一個百年來始終堅持做自己的個性品牌,這是喜歡它的原因,有人說,瑪莎拉蒂是一個“全靠浪(聲浪)”的品牌,這個說法對也不對,不可否認,瑪莎拉蒂在聲浪方面所下的功夫確實無人能敵,但是其在豪華體驗上也是讓人不得不翹起個大拇指說“Good”!本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※回頭車貨運收費標準

  • 深入理解React:懶加載(lazy)實現原理

    目錄

    • 代碼分割
    • React的懶加載
      • import() 原理
      • React.lazy 原理
      • Suspense 原理
    • 參考

    1.代碼分割

    (1)為什麼要進行代碼分割?

    現在前端項目基本都採用打包技術,比如 Webpack,JS邏輯代碼打包後會產生一個 bundle.js 文件,而隨着我們引用的第三方庫越來越多或業務邏輯代碼越來越複雜,相應打包好的 bundle.js 文件體積就會越來越大,因為需要先請求加載資源之後,才會渲染頁面,這就會嚴重影響到頁面的首屏加載。

    而為了解決這樣的問題,避免大體積的代碼包,我們則可以通過技術手段對代碼包進行分割,能夠創建多個包並在運行時動態地加載。現在像 Webpack、 Browserify等打包器都支持代碼分割技術。

    (2)什麼時候應該考慮進行代碼分割?

    這裏舉一個平時開發中可能會遇到的場景,比如某個體積相對比較大的第三方庫或插件(比如JS版的PDF預覽庫)只在單頁應用(SPA)的某一個不是首頁的頁面使用了,這種情況就可以考慮代碼分割,增加首屏的加載速度。

    2.React的懶加載

    示例代碼:

    import React, { Suspense } from 'react';
    
    const OtherComponent = React.lazy(() => import('./OtherComponent'));
    
    function MyComponent() {
      return (
        <div>
          <Suspense fallback={<div>Loading...</div>}>
            <OtherComponent />
          </Suspense>
        </div>
      );
    }
    

    如上代碼中,通過 import() React.lazySuspense 共同一起實現了 React 的懶加載,也就是我們常說了運行時動態加載,即 OtherComponent 組件文件被拆分打包為一個新的包(bundle)文件,並且只會在 OtherComponent 組件渲染時,才會被下載到本地。

    那麼上述中的代碼拆分以及動態加載究竟是如何實現的呢?讓我們來一起探究其原理是怎樣的。

    import() 原理

    import() 函數是由TS39提出的一種動態加載模塊的規範實現,其返回是一個 promise。在瀏覽器宿主環境中一個import()的參考實現如下:

    function import(url) {
      return new Promise((resolve, reject) => {
        const script = document.createElement("script");
        const tempGlobal = "__tempModuleLoadingVariable" + Math.random().toString(32).substring(2);
        script.type = "module";
        script.textContent = `import * as m from "${url}"; window.${tempGlobal} = m;`;
    
        script.onload = () => {
          resolve(window[tempGlobal]);
          delete window[tempGlobal];
          script.remove();
        };
    
        script.onerror = () => {
          reject(new Error("Failed to load module script with URL " + url));
          delete window[tempGlobal];
          script.remove();
        };
    
        document.documentElement.appendChild(script);
      });
    }
    

    當 Webpack 解析到該import()語法時,會自動進行代碼分割。

    React.lazy 原理

    以下 React 源碼基於 16.8.0 版本

    React.lazy 的源碼實現如下:

    export function lazy<T, R>(ctor: () => Thenable<T, R>): LazyComponent<T> {
      let lazyType = {
        $$typeof: REACT_LAZY_TYPE,
        _ctor: ctor,
        // React uses these fields to store the result.
        _status: -1,
        _result: null,
      };
    
      return lazyType;
    }
    

    可以看到其返回了一個 LazyComponent 對象。

    而對於 LazyComponent 對象的解析:

    ...
    case LazyComponent: {
      const elementType = workInProgress.elementType;
      return mountLazyComponent(
        current,
        workInProgress,
        elementType,
        updateExpirationTime,
        renderExpirationTime,
      );
    }
    ...
    
    function mountLazyComponent(
      _current,
      workInProgress,
      elementType,
      updateExpirationTime,
      renderExpirationTime,
    ) { 
      ...
      let Component = readLazyComponentType(elementType);
      ...
    }
    
    // Pending = 0, Resolved = 1, Rejected = 2
    export function readLazyComponentType<T>(lazyComponent: LazyComponent<T>): T {
      const status = lazyComponent._status;
      const result = lazyComponent._result;
      switch (status) {
        case Resolved: {
          const Component: T = result;
          return Component;
        }
        case Rejected: {
          const error: mixed = result;
          throw error;
        }
        case Pending: {
          const thenable: Thenable<T, mixed> = result;
          throw thenable;
        }
        default: { // lazyComponent 首次被渲染
          lazyComponent._status = Pending;
          const ctor = lazyComponent._ctor;
          const thenable = ctor();
          thenable.then(
            moduleObject => {
              if (lazyComponent._status === Pending) {
                const defaultExport = moduleObject.default;
                lazyComponent._status = Resolved;
                lazyComponent._result = defaultExport;
              }
            },
            error => {
              if (lazyComponent._status === Pending) {
                lazyComponent._status = Rejected;
                lazyComponent._result = error;
              }
            },
          );
          // Handle synchronous thenables.
          switch (lazyComponent._status) {
            case Resolved:
              return lazyComponent._result;
            case Rejected:
              throw lazyComponent._result;
          }
          lazyComponent._result = thenable;
          throw thenable;
        }
      }
    }
    

    注:如果 readLazyComponentType 函數多次處理同一個 lazyComponent,則可能進入Pending、Rejected等 case 中。

    從上述代碼中可以看出,對於最初 React.lazy() 所返回的 LazyComponent 對象,其 _status 默認是 -1,所以首次渲染時,會進入 readLazyComponentType 函數中的 default 的邏輯,這裏才會真正異步執行 import(url)操作,由於並未等待,隨後會檢查模塊是否 Resolved,如果已經Resolved了(已經加載完畢)則直接返回moduleObject.default(動態加載的模塊的默認導出),否則將通過 throw 將 thenable 拋出到上層。

    為什麼要 throw 它?這就要涉及到 Suspense 的工作原理,我們接着往下分析。

    Suspense 原理

    由於 React 捕獲異常並處理的代碼邏輯比較多,這裏就不貼源碼,感興趣可以去看 throwException 中的邏輯,其中就包含了如何處理捕獲的異常。簡單描述一下處理過程,React 捕獲到異常之後,會判斷異常是不是一個 thenable,如果是則會找到 SuspenseComponent ,如果 thenable 處於 pending 狀態,則會將其 children 都渲染成 fallback 的值,一旦 thenable 被 resolve 則 SuspenseComponent 的子組件會重新渲染一次。

    為了便於理解,我們也可以用 componentDidCatch 實現一個自己的 Suspense 組件,如下:

    class Suspense extends React.Component {
      state = {
        promise: null
      }
    
      componentDidCatch(err) {
        // 判斷 err 是否是 thenable
        if (err !== null && typeof err === 'object' && typeof err.then === 'function') {
          this.setState({ promise: err }, () => {
            err.then(() => {
              this.setState({
                promise: null
              })
            })
          })
        }
      }
    
      render() {
        const { fallback, children } = this.props
        const { promise } = this.state
        return <>{ promise ? fallback : children }</>
      }
    }
    

    小結

    至此,我們分析完了 React 的懶加載原理。簡單來說,React利用 React.lazyimport()實現了渲染時的動態加載 ,並利用Suspense來處理異步加載資源時頁面應該如何显示的問題。

    3.參考

    代碼分割– React

    動態import – MDN – Mozilla

    proposal-dynamic-import

    React Lazy 的實現原理

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

    【其他文章推薦】

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

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

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

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

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

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

  • Spark文檔閱讀之二:Programming Guides – Quick Start

    Spark文檔閱讀之二:Programming Guides – Quick Start

    Quick Start: https://spark.apache.org/docs/latest/quick-start.html

     

    在Spark 2.0之前,Spark的編程接口為RDD (Resilient Distributed Dataset)。而在2.0之後,RDDs被Dataset替代。Dataset很像RDD,但是有更多優化。RDD仍然支持,不過強烈建議切換到Dataset,以獲得更好的性能。 RDD文檔: https://spark.apache.org/docs/latest/rdd-programming-guide.html Dataset文檔: https://spark.apache.org/docs/latest/sql-programming-guide.html  

    一、最簡單的Spark Shell交互分析

    scala> val textFile = spark.read.textFile("README.md")   # 構建一個Dataset
    textFile: org.apache.spark.sql.Dataset[String] = [value: string]
    
    scala> textFile.count()  # Dataset的簡單計算
    res0: Long = 104 
    
    scala> val linesWithSpark = textFile.filter(line => line.contain("Spark"))  # 由現有Dataset生成新Dataset
    res1: org.apache.spark.sql.Dataset[String] = [value: string]
    # 等價於:
    # res1 = new Dataset()
    # for line in textFile:
    #     if line.contain("Spark"):
    #         res1.append(line)
    # linesWithSpark = res1
    
    scala> linesWithSpark.count()
    res2: Long = 19
    
    # 可以將多個操作串行起來
    scala> textFile.filter(line => line.contain("Spark")).count()
    res3: Long = 19

     

    進一步的Dataset分析:

    scala> textFile.map(line => line.split(" ").size).reduce((a,b) => if (a > b) a else b)
    res12: Int = 16
    # 其實map和reduce就是兩個普通的算子,不要被MapReduce中一個map配一個reduce、先map后reduce的思想所束縛
    # map算子就是對Dataset的元素X計算fun(X),並且將所有f(X)作為新的Dataset返回
    # reduce算子其實就是通過兩兩計算fun(X,Y)=Z,將Dataset中的所有元素歸約為1個值
    
    # 也可以引入庫進行計算
    scala> import java.lang.Math
    import java.lang.Math
    
    scala> textFile.map(line => line.split(" ").size).reduce((a, b) => Math.max(a, b))
    res14: Int = 16
    
    # 還可以使用其他算子
    scala> val wordCounts = textFile.flatMap(line => line.split(" ")).groupByKey(identity).count()
    
    # flatMap算子也是對Dataset的每個元素X執行fun(X)=Y,只不過map的res是
    #     res.append(Y),如[[Y11, Y12], [Y21, Y22]],結果按元素區分
    # 而flatMap是
    #     res += Y,如[Y11, Y12, Y21, Y22],各元素結果合在一起
    
    # groupByKey算子將Dataset的元素X作為參數傳入進行計算f(X),並以f(X)作為key進行分組,返回值為KeyValueGroupedDataset類型
    # 形式類似於(key: k; value: X1, X2, ...),不過KeyValueGroupedDataset不是一個Dataset,value列表也不是一個array
    # 注意:這裏的textFile和textFile.flatMap都是Dataset,不是RDD,groupByKey()中可以傳func;如果以sc.textFile()方法讀文件,得到的是RDD,groupByKey()中間不能傳func
    
    # identity就是函數 x => x,即返回自身的函數
    
    # KeyValueGroupedDataset的count()方法返回(key, len(value))列表,結果是Dataset類型
    
    scala> wordCounts.collect()
    res37: Array[(String, Long)] = Array((online,1), (graphs,1), ...
    # collect操作:將分佈式存儲在集群上的RDD/Dataset中的所有數據都獲取到driver端

     

    數據的cache:

    scala> linesWithSpark.cache()  # in-memory cache,讓數據在分佈式內存中緩存
    res38: linesWithSpark.type = [value: string]
    
    scala> linesWithSpark.count()
    res41: Long = 19

     

    二、最簡單的獨立Spark任務(spark-submit提交)

    需提前安裝sbt,sbt是scala的編譯工具(Scala Build Tool),類似java的maven。 brew install sbt   1)編寫SimpleApp.scala

    import org.apache.spark.sql.SparkSession
    
    object SimpleApp {
        def main(args: Array[String]) {
            val logFile = "/Users/dxm/work-space/spark-2.4.5-bin-hadoop2.7/README.md"
            val spark = SparkSession.builder.appName("Simple Application").getOrCreate()
            val logData = spark.read.textFile(logFile).cache()
            val numAs = logData.filter(line => line.contains("a")).count()  # 包含字母a的行數
            val numBs = logData.filter(line => line.contains("b")).count()  # 包含字母b的行數
            println(s"Lines with a: $numAs, Lines with b: $numBs")
            spark.stop()
        }
    }

     

    2)編寫sbt依賴文件build.sbt

    name := "Simple Application"
    
    version := "1.0"
    
    scalaVersion := "2.12.10"
    
    libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.4.5"

     

    其中,”org.apache.spark” %% “spark-sql” % “2.4.5”這類庫名可以在網上查到,例如https://mvnrepository.com/artifact/org.apache.spark/spark-sql_2.10/1.0.0

     

    3)使用sbt打包 目錄格式如下,如果SimpleApp.scala和build.sbt放在一個目錄下會編不出來

    $ find .
    .
    ./build.sbt
    ./src
    ./src/main
    ./src/main/scala
    ./src/main/scala/SimpleApp.scala

     

    sbt目錄格式要求見官方文檔 https://www.scala-sbt.org/1.x/docs/Directories.html

    src/
      main/
        resources/
           <files to include in main jar here>
        scala/
           <main Scala sources>
        scala-2.12/
           <main Scala 2.12 specific sources>
        java/
           <main Java sources>
      test/
        resources
           <files to include in test jar here>
        scala/
           <test Scala sources>
        scala-2.12/
           <test Scala 2.12 specific sources>
        java/
           <test Java sources>

     

    使用sbt打包

    # 打包
    $ sbt package
    ...
    [success] Total time: 97 s (01:37), completed 2020-6-10 10:28:24
    # jar包位於 target/scala-2.12/simple-application_2.12-1.0.jar

     

    4)提交並執行Spark任務

    $ bin/spark-submit --class "SimpleApp" --master spark://xxx:7077 ../scala-tests/SimpleApp/target/scala-2.12/simple-application_2.12-1.0.jar
    # 報錯:Caused by: java.lang.ClassNotFoundException: scala.runtime.LambdaDeserialize
    # 參考:https://stackoverflow.com/questions/47172122/classnotfoundexception-scala-runtime-lambdadeserialize-when-spark-submit
    # 這是spark版本和scala版本不匹配導致的

     

    查詢spark所使用的scala的版本

    $ bin/spark-shell --master spark://xxx:7077
    
    scala> util.Properties.versionString
    res0: String = version 2.11.12

     

    修改build.sbt: scalaVersion := “2.11.12” 從下載頁也可驗證,下載的spark 2.4.5使用的是scala 2.11  

     

    重新sbt package,產出位置變更為target/scala-2.11/simple-application_2.11-1.0.jar 再次spark-submit,成功

     

    $ bin/spark-submit --class "SimpleApp" --master spark://xxx:7077 ../scala-tests/SimpleApp/target/scala-2.11/simple-application_2.11-1.0.jar 
    Lines with a: 61, Lines with b: 30

     

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

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※回頭車貨運收費標準

  • 用 Explain 命令分析 MySQL 的 SQL 執行

    用 Explain 命令分析 MySQL 的 SQL 執行

    在上一篇文章《MySQL常見加鎖場景分析》中,我們聊到行鎖是加在索引上的,但是複雜的 SQL 往往包含多個條件,涉及多個索引,找出 SQL 執行時使用了哪些索引對分析加鎖場景至關重要。

    比如下面這樣的 SQL:

    mysql> delete from t1 where id = 1 or val = 1
    

    其中 id 和 val 都是索引,那麼執行時使用到了哪些索引,加了哪些鎖呢?為此,我們需要使用 explain 來獲取 MySQL 執行這條 SQL 的執行計劃。

    什麼是執行計劃呢?簡單來說,就是 SQL 在數據庫中執行時的表現情況,通常用於 SQL 性能分析、優化和加鎖分析等場景,執行過程會在 MySQL 查詢過程中由解析器,預處理器和查詢優化器共同生成。

    MySQL 查詢過程

    如果能搞清楚 MySQL 是如何優化和執行查詢的,不僅對優化查詢一定會有幫助,還可以通過分析使用到的索引來判斷最終的加鎖場景。

    下圖是MySQL執行一個查詢的過程。實際上每一步都比想象中的複雜,尤其優化器,更複雜也更難理解。本文只給予簡單的介紹。

    MySQL查詢過程如下:

    • 客戶端發送一條查詢給服務器。
    • 服務器先檢查查詢緩存,如果命中了緩存,則立刻返回存儲在緩存中的結果。否則進入下一階段。
    • 服務器端進行SQL解析、預處理,再由優化器生成對應的執行計劃。
    • MySQL根據優化器生成的執行計劃,再調用存儲引擎的API來執行查詢。
    • 將結果返回給客戶端。

    執行計劃

    MySQL會解析查詢,並創建內部數據結構(解析樹),並對其進行各種優化,包括重寫查詢、決定表的讀取順序、選擇合適的索引等。

    用戶可通過關鍵字提示(hint)優化器,從而影響優化器的決策過程。也可以通過 explain 了解 數據庫是如何進行優化決策的,並提供一個參考基準,便於用戶重構查詢和數據庫表的 schema、修改數據庫配置等,使查詢盡可能高效。

    下面,我們依次介紹 explain 中相關輸出參數,並以實際例子解釋這些參數的含義。

    select_type

    查詢數據的操作類型,有如下

    • simple 簡單查詢,不包含子查詢或 union,如下圖所示,就是最簡單的查詢語句。
    • primary 是 SQL 中包含複雜的子查詢,此時最外層查詢標記為該值。

    • derived 是 SQL 中 from 子句中包含的子查詢被標記為該值,MySQL 會遞歸執行這些子查詢,把結果放在臨時表。下圖展示了上述兩種類型。

    • subquery 是 SQL 在 select 或者 where 里包含的子查詢,被標記為該值。
    • dependent subquery:子查詢中的第一個 select,取決於外側的查詢,一般是 in 中的子查詢。
    • union 是 SQL 在出現在 union 關鍵字之後的第二個 select ,被標記為該值;若 union 包含在 from 的子查詢中,外層select 被標記為 derived。

    • union result 從 union 表獲取結果的 select。下圖展示了 union 和 union result 的 SQL 案例。

    • dependent union 也是 union 關鍵字之後的第二個或者後邊的那個 select 語句,和 dependent subquery 一樣,取決於外面的查詢。

    type

    表的連接類型,其性能由高到低排列為 system,const,eq_ref,ref,range,index 和 all。

    • system 表示表只有一行記錄,相當於系統表。如下圖所示,因為 from 的子查詢派生的表只有一行數據,所以 primary 的表連接類型為 system。
    • const 通過索引一次就找到,只匹配一行數據,用於常數值比較PRIMARY KEY 或者 UNIQUE索引。
    • eq_ref 唯一性索引掃描,對於每個索引鍵,表中只有一條記錄與之匹配,常用於主鍵或唯一索引掃描。對於每個來自前邊的表的行組合,從該表中讀取一行。它是除了 const 類型外最好的連接類型。

      如下圖所示,對錶 t1 查詢的 type 是 ALL,表示全表掃描,然後 t1 中每一行數據都來跟 t2.id 這個主鍵索引進行對比,所以 t2 表的查詢就是 eq_ref。

    • ref 非唯一性索引掃描,返回匹配某個單獨值的所有行,和 eq_ref 的區別是索引是非唯一索引,具體案例如下所示。
    • range 只檢查給定範圍的行,使用一個索引來選擇行,當使用 =, between, >, <, 和 in 等操作符,並使用常數比較關鍵列時。如下圖所示,其中 id 為唯一索引,而 val 是非唯一索引。
    • index 與 ALL 類型類似,唯一區別就是只遍歷索引樹讀取索引值,比 ALL 讀取所有數據行要稍微快一些,因為索引文件通常比數據文件小。這裏涉及 MySQL 的索引覆蓋

    • ALL 全表掃描,通常情況下性能很差,應該避免。

    possible_keys,key 和 key_len

    possible_key 列指出 MySQL 可能使用哪個索引在該表中查找。如果該列為 NULL,則沒有使用相關索引。需要檢查 where 子句條件來創建合適的索引提高查詢效率。

    key 列显示 MySQL 實際決定使用的索引。如果沒有選擇索引,則值為 NULL。

    key_len 显示 MySQL 決定使用索引的長度。如果鍵為 NULL,則本列也為 NULL,使用的索引長度,在保證精確度的情況下,越短越好。因為越短,索引文件越小,需要的 I/O次數也越少。

    由上圖可以看出,對於 select * from t2 where id = 1 or val = 1這個語句,可以使用 PRIMARY 或者 idx_t2_val 索引,實際使用了 idx_t2_val 索引,索引的長度為5。

    這些其實是我們分析加鎖場景最為關心的字段,後續文章會具體講解如何根據這些字段和其他工具一起判斷複雜 SQL 到底加了哪些鎖。

    ref

    ref 列表示使用其他表的哪個列或者常數來從表中選擇行。如下圖所示,從 t2 讀取數據時,要判斷 t2.id = t1.id,所以 ref 就是 mysql.t1.id

    rows 和 filtered

    rows 列显示 MySQL 認為它執行查詢時必須檢查的行數。

    filtered 列表明了 SQL 語句執行后返回結果的行數占讀取行數的百分比,值越大越好。MySQL 會使用 Table Filter 來讀取出來的行數據進行過濾,理論上,讀取出來的行等於返回結果的行數時效率最高,過濾的比率越多,效率越低。

    如上圖所示,t1表中有三條數據,rows 為 3,表示所有行都要讀取出來。根據 val = 3 這個 table filter 過濾,只返回一行數據,所以 filtered 比例為33.33%,

    extra

    包含不適合在其他列中显示但十分重要的額外信息。常見的值如下

    • using index 表示 select 操作使用了覆蓋索引,避免了訪問表的數據行,效率不錯。

    • using where 子句用於限制哪一行。也就是讀取數據后使用了 Table Filter 進行過濾。

      如下圖所示,因為 id 和 val 都是有索引的,所以 select * 也是可以直接使用覆蓋索引讀取數據,所以 extra 中有 using index。而因為只使用 val 索引讀取了3行數據,還是通過 where 子句進行過濾,filtered為 55%,所以 extra 中使用了 using where。

    • using filesort MySQL 會對數據使用一個外部的索引排序,而不是按照表內的索引順序進行讀取,若出現該值,應該優化 SQL 語句。如下圖所示,其中 val 列沒有索引,所以無法使用索引順序排序讀取。
    • using temporary 使用臨時表保存中間結果,比如,MySQL 在對查詢結果排序時使用臨時表,常用於 order by 和 group by,如果出現該值,應該優化 SQL。根據我的經驗,group by 一個無索引列,或者ORDER BY 或 GROUP BY 的列不是來自JOIN語句序列的第一個表,就會產生臨時表。

    • using join buffer 使用連接緩存。如下圖所示,展示了連接緩存和臨時表。關於連接緩存的內容,大家可以自行查閱,後續有時間在寫文章解釋。

    • distinct 發現第一個匹配后,停止為當前的行組合搜索更多的行

    後記

    通過 explain 了解到 SQL 的執行計劃后,我們不僅可以了解 SQL 執行時使用的索引,判斷加鎖場景,還可以針對其他信息對 SQL 進行優化分析,比如將 type 類型從 index 優化到 ref 等。

    個人博客,歡迎來玩

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

    【其他文章推薦】

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

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

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

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

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

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

  • HotCorner:讓Windows 10擁有macOS的觸發角特性!

    HotCorner:讓Windows 10擁有macOS的觸發角特性!

    目錄

    • 簡介
    • 軟件功能
    • 下載
    • 安裝
    • 卸載
    • 使用
    • License
    • 作者
    • FAQ

    簡介

    macOS上有一個很方便的功能:“觸發角”。通過這個功能可以設置當鼠標移動到屏幕的四個角時的觸發事件,例如觸發啟動屏幕保護程序等,显示桌面等功能。和我們習慣的熱鍵相對應,macOS將其稱之為“Hot Corners(熱角)”。筆者接下來要介紹的軟件“HotCorner“就是用於讓Windows系統擁有像macOS那樣的觸發角,實現下面動圖展示的效果:

    當鼠標移動到屏幕的左上角時,自動打開Windows的時間軸試圖,實現快捷切換任務。

    這個程序來源於一個國外大神(Google的信息安全工程師)Tavis Ormandy 的一個小項目 hotcorner,他創作這個項目是因為習慣於一款Linux操作系統桌面:GNOME 3,這款桌面可以在鼠標移動到左上角時觸發任務視圖。他發現每當自己使用Windows 10時,總是會忘記Windows中並沒有這個功能,四處尋找替代軟件都無法令他滿意,因此自己用C語言手擼了一個小程序來實現這個功能。但這個小程序只有一個功能:屏幕左上角觸發Windows時間軸視圖。並且軟件的安裝,卸載都需要通過命令行或者手動實現,十分不方便。

    筆者在原先的項目基礎上做出了如下改動:

    1. 用屏幕的左下角來觸發開始菜單
    2. 將軟件打包成安裝引導程序(安裝包)
    3. 給軟件添加圖標
    4. 安裝時可選擇軟件開機啟動
    5. 編寫中文文檔

    下面一張動圖演示了筆者添加的左下角觸發開始菜單的功能

    軟件功能

    • 當鼠標移動至屏幕左上角時显示Windows 10時間軸視圖
    • 當鼠標移動至屏幕右下角時显示Windows 開始菜單

    下載

    Github地址:下載地址

    碼雲地址:下載地址

    如果你不打算參与本軟件開發,只需要下載HotcornerInstaller.exe這個安裝程序即可
    國內推薦使用碼雲地址進行下載,速度比較快,但如果你需要提交issue,請前往Github地址。

    安裝

    從上述下載地址將HotcornerInstaller.exe下載下來之後,雙擊打開即可開始安裝。

    卸載

    找到軟件的安裝位置(默認是C:\Program Files (x86)\HotCorner),雙擊該文件夾下的unins000.exe即可完成卸載。在卸載之前請先停止軟件運行(同時按下Ctrl+Alt+C)。

    使用

    軟件安裝完成之後會自動添加到開始菜單的應用列表中,在其中找到HotCorner,單擊之後軟件即可後台運行。如果你使用了如圖所示的屏幕縮放,並且縮放比例不是100%時,則需要進行下面的配置

    正常情況下,軟件可以自動獲取屏幕的高度,但是在系統使用屏幕縮放時,會導致軟件獲取到的不是屏幕的真實高度,因此你需要編輯軟件安裝路徑(默認是C:\Program Files (x86)\HotCorner)下的config.txt文件,在這個文件中寫入屏幕的真實高度,例如圖中的屏幕真實高度為1080(無單位),然後重啟軟件。(config.txt中的默認值是0,表示自動獲取屏幕高度。)

    在軟件運行過程中同時按下Ctrl+Alt+C可以關閉程序

    License

    代碼使用GPL3協議進行開源,如需使用代碼請遵循CPL3協議相關規定。

    作者

    • Tavis Ormandy @taviso – Original Author
    • Ahmed Samy @asamy – HotKey support
    • Yuchao Huang @misterchaos – Application Package

    FAQ

    • Q: 屏幕左上角可以觸發時間軸視圖,但是屏幕右下角沒有反應?

    • A: 你可能使用了屏幕縮放,查看配置說明

    • Q: 我想修改屏幕角觸發的事件,怎麼辦?

    • A: 目前只能自己下載源代碼進行修改,然後重新編譯運行。

    • Q: 軟件運行之後怎麼關閉?

    • A: 在軟件運行過程中同時按下Ctrl+Alt+C可以關閉程序

    • Q: 怎麼讓軟件在開機時運行?

    • A: 在安裝過程中可以選擇開機啟動,如果安裝時沒有選擇,可以手動實現(方法自己百度即可)

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

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※回頭車貨運收費標準

  • 漢蘭達提車等幾個月,不如看看這款2.0T+9AT的7座SUV

    漢蘭達提車等幾個月,不如看看這款2.0T+9AT的7座SUV

    0T+愛信6AT雖然動力數據不及大指揮官,但勝在穩定可靠。豐田在漢蘭達的動力調校上要比Jeep更為得心應手,低轉下的扭矩較為充沛,油門調校也有一貫日系車的風格,初段頗為靈敏。在零百成績方面,漢蘭達為9。13秒。儘管如此,在高速上再加速時,漢蘭達依舊顯得底氣十足。

    如果要買一輛7座中型SUV來作為家庭出行的首選,我想很多人都會第一時間想到漢蘭達。畢竟這麼多年的口碑擺在那裡,各方面的實力都較為均衡。奈何漢蘭達的產能有限,導致不少地區要等好幾個月,甚至加價才能提車。

    幾年前,福特推出銳界試圖撼動漢蘭達的地位,結果也只是成了不少人買不到漢蘭達,退而求其次的選擇。這回Jeep推出大指揮官也是試圖重新攪動這個市場,好好地打擊一下漢蘭達,那究竟指揮官有沒有這樣的實力呢?虎哥就為大家好好分析一下。

    從動力參數來看,大指揮官無論是最大馬力還是最大扭矩都比漢蘭達多不少,而且在整備質量方面,大指揮官比漢蘭達還要輕75kg,相當於一個成年男性的質量。不過,參數只是一個方面,更重要的還是動力匹配。

    大指揮官上的這副2.0T發動機與Giulia上的是同根同源,與之匹配的是ZF的9AT變速箱。日常駕駛時,能發現這副9AT還是偏向於平順的調校,低速蠕行時沒有什麼頓挫。

    這樣的調校會導致大指揮官在急加速時的換擋偏慢,好在這副2.0T的機器底氣較足,很多時候並不需要降太多的擋位便可以完成加速。大指揮官實測的零百成績能少於8秒,比漢蘭達要快不少。大指揮官在走一些顛簸路時,濾震不錯,有一定的厚實感,只是偏軟的彈簧導致剎車時容易點頭。

    漢蘭達的2.0T+愛信6AT雖然動力數據不及大指揮官,但勝在穩定可靠。豐田在漢蘭達的動力調校上要比Jeep更為得心應手,低轉下的扭矩較為充沛,油門調校也有一貫日系車的風格,初段頗為靈敏。

    在零百成績方面,漢蘭達為9.13秒。儘管如此,在高速上再加速時,漢蘭達依舊顯得底氣十足。底盤調校上,漢蘭達偏重於舒適,懸挂的工作也較為無感。走爛路時,漢蘭達的濾震厚實,無論是駕駛員還是乘客都坐得較為舒適。

    大指揮官的二三排

    從上面的對比表格不難看出,漢蘭達更傾向於做好第二排,所以第二排在最小時也不至於頂到前排。同時,全平的中央地板也為其加分不少。但是在第三排方面,明顯就不如大指揮官。

    漢蘭達的二三排

    雖然大指揮官的二排在最小和最大腿部空間上都不如漢蘭達,但是第三排在最好的情況下能調出四指的腿部空間。不過這還是有點雞肋,滿載時,不僅三排的人會坐得比較局促,連二排乘客也會隨之遭殃。

    從上面的配置對比來看,在相同指導價下,大指揮官的配置表現是要略微好於漢蘭達。儘管這款漢蘭達的售價高達30多萬,但依舊採用的是鹵素大燈,車窗一鍵升降也僅裝備於前排,這些都是不應該的。

    總結

    大指揮官的表現雖然不錯,但在這個級別消費者最需要的舒適和大空間方面,還是與漢蘭達拉不開距離。倒是在動力和配置方面,能展現出自己的優勢,這樣的表現與銳界有幾分相似。對於消費者而言,多一個選擇總歸還是一件好事情,但恐怕大指揮官還是無法撼動漢蘭達的地位。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

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

    ※台北網頁設計公司全省服務真心推薦

    ※想知道最厲害的網頁設計公司"嚨底家"!

    ※推薦評價好的iphone維修中心

  • 比思域更快的大眾家轎才14.59萬起步,買車還不用排隊

    比思域更快的大眾家轎才14.59萬起步,買車還不用排隊

    這樣的加速放眼這個價位,可以說是數一數二了。當你大腳油門跺下去時,馬牌的MC5輪胎雖然捉地力不錯,但還是響着胎竄出去了,確實有那麼點性能車的味道。儘管動力確實不俗,但是代號DQ380的7速濕式雙離合變速箱還是小小地拖了一下後腿。

    大眾在中國深耕多年,絕大部分車系都賣得相當不錯,今天要給大家講講的是奢適寬體轎跑——凌渡。這款車在今年1至3月累計賣出了超過4萬台,實力不用小覷。

    動力可以說是凌渡一個小小的賣點,TSI+DSG這套黃金組合併沒有讓我們失望。即便是凌渡的1.4T低功版車型,在實測時,也能有9.1s左右的零百成績。不過在起步時不能憋轉速,這點對於那些玩家來說,還是有點小遺憾。

    1.8T車型的零百成績為7.9s,表現比1.4T車型好不少。雖然都是7擋雙離合,但1.8T車型採用的是7擋濕式雙離合。這套雙離合較好地改善了凌渡低速蠕行時的頓挫問題,1/2擋之間的切換不再顯得猶豫。

    不過這套7擋雙離合也是有一點點問題,那就是為了平順性,犧牲了一點換擋速度。急加速時的降擋會稍微慢了那麼一點,但也在一個合理的範圍內。如果不是一個對駕駛有很高要求的人,這樣的動力響應已然不錯。

    2.0T GTS車型可以說是凌渡的精華所在,220馬力推動僅1475kg的車身,出來的便是6.9s的零百加速。這樣的加速放眼這個價位,可以說是數一數二了。當你大腳油門跺下去時,馬牌的MC5輪胎雖然捉地力不錯,但還是響着胎竄出去了,確實有那麼點性能車的味道。

    儘管動力確實不俗,但是代號DQ380的7速濕式雙離合變速箱還是小小地拖了一下後腿。這套變速箱的表現與1.8T車型上的那副相近,都是平順為先,急加速時的降擋還是稍顯拖沓了一些。

    除了轎跑這個賣點外,奢適也是凌渡的一大優點。前懸架採用的是麥弗遜式獨立懸架,后懸架則為多連桿獨立懸架,這種結構在同級車中極為常見,但凌渡的調校在操控與舒適之間拿捏得恰到好處。

    在過濾路面的震動時,凌渡表現出了足夠的厚實感。即便是在遇到一些大坑窪時,車身的拋跳也不會很明顯。走高速遇到一些接縫位置時,凌渡的底盤貼服性相當不錯。

    既然說是奢適寬體轎跑,空間自然不得不提。175cm的體驗者坐在前排時,能獲得3指左右的頭部空間,同時前排的包裹性和舒適性都做得不錯,只是中央扶手的位置稍微低了一些。

    二排來看,由於車身偏低矮,所以175cm的體驗者坐在裏面直接就頂頭了,還好腿部依然有兩拳的空間。凌渡的二排中央地板凸起較為明顯,對於中間的乘客不太友好,不過勝在帶有中央頭枕。同時,整個二排的橫向空間表現不錯,坐滿三人時也不會覺得過於擁擠,這點還是值得表揚。

    總結

    可以看到凌渡這款車表現得頗為全面,無愧於奢適寬體轎跑的名號。動力水平高,儘管換擋稍稍慢了一些,但整體平順性確實好;底盤調校得有高級感,容易討好乘客;最大問題恐怕還是二排頭部空間稍微小了一些。目前凌渡的終端優惠能有5萬塊左右,喜歡的人可以果斷出手了。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

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

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

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

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

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

    ※超省錢租車方案

  • 用python做時間序列預測九:ARIMA模型簡介

    用python做時間序列預測九:ARIMA模型簡介

    本篇介紹時間序列預測常用的ARIMA模型,通過了解本篇內容,將可以使用ARIMA預測一個時間序列。

    什麼是ARIMA?

    • ARIMA是’Auto Regressive Integrated Moving Average’的簡稱。
    • ARIMA是一種基於時間序列歷史值和歷史值上的預測誤差來對當前做預測的模型。
    • ARIMA整合了自回歸項AR和滑動平均項MA。
    • ARIMA可以建模任何存在一定規律的非季節性時間序列。
    • 如果時間序列具有季節性,則需要使用SARIMA(Seasonal ARIMA)建模,後續會介紹。

    ARIMA模型參數

    ARIMA模型有三個超參數:p,d,q

    • p
      AR(自回歸)項的階數。需要事先設定好,表示y的當前值和前p個歷史值有關。
    • d
      使序列平穩的最小差分階數,一般是1階。非平穩序列可以通過差分來得到平穩序列,但是過度的差分,會導致時間序列失去自相關性,從而失去使用AR項的條件。
    • q
      MA(滑動平均)項的階數。需要事先設定好,表示y的當前值和前q個歷史值AR預測誤差有關。實際是用歷史值上的AR項預測誤差來建立一個類似歸回的模型。

    ARIMA模型表示

    • AR項表示
      一個p階的自回歸模型可以表示如下:

      c是常數項,εt是隨機誤差項。
      對於一個AR(1)模型而言:
      當 ϕ1=0 時,yt 相當於白噪聲;
      當 ϕ1=1 並且 c=0 時,yt 相當於隨機遊走模型;
      當 ϕ1=1 並且 c≠0 時,yt 相當於帶漂移的隨機遊走模型;
      當 ϕ1<0 時,yt 傾向於在正負值之間上下浮動。

    • MA項表示
      一個q階的預測誤差回歸模型可以表示如下:

      c是常數項,εt是隨機誤差項。
      yt 可以看成是歷史預測誤差的加權移動平均值,q指定了歷史預測誤差的期數。

    • 完整表示

      即: 被預測變量Yt = 常數+Y的p階滯后的線性組合 + 預測誤差的q階滯后的線性組合

    ARIMA模型定階

    看圖定階

    差分階數d
    • 如果時間序列本身就是平穩的,就不需要差分,所以此時d=0。
    • 如果時間序列不平穩,那麼主要是看時間序列的acf圖,如果acf表現為10階或以上的拖尾,那麼需要進一步的差分,如果acf表現為1階截尾,則可能是過度差分了,最好的差分階數是使acf先拖尾幾階,然後截尾。
    • 有的時候,可能在2個階數之間無法確定用哪個,因為acf的表現差不多,那麼就選擇標準差小的序列。
    • 下面是原時間序列、一階差分后、二階差分后的acf圖:

      可以看到,原序列的acf圖的拖尾階數過高了,而二階差分后的截尾階數過小了,所以一階差分更合適。

    python代碼:

    import numpy as np, pandas as pd
    from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
    import matplotlib.pyplot as plt
    plt.rcParams.update({'figure.figsize':(9,7), 'figure.dpi':120})
    
    # Import data : Internet Usage per Minute
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/wwwusage.csv', names=['value'], header=0)
    
    # Original Series
    fig, axes = plt.subplots(3, 2, sharex=True)
    axes[0, 0].plot(df.value); axes[0, 0].set_title('Original Series')
    plot_acf(df.value, ax=axes[0, 1])
    
    # 1st Differencing
    axes[1, 0].plot(df.value.diff()); axes[1, 0].set_title('1st Order Differencing')
    plot_acf(df.value.diff().dropna(), ax=axes[1, 1])
    
    # 2nd Differencing
    axes[2, 0].plot(df.value.diff().diff()); axes[2, 0].set_title('2nd Order Differencing')
    plot_acf(df.value.diff().diff().dropna(), ax=axes[2, 1])
    
    plt.show()
    
    AR階數p

    AR的階數p可以通過pacf圖來設定,因為AR各項的係數就代表了各項自變量x對因變量y的偏自相關性。

    可以看到,lag1,lag2之後,偏自相關落入了藍色背景區間內,表示不相關,所以這裏階數可以選擇2,或者保守點選擇1。

    MA階數q

    MA階數通過acf圖來設定,因為MA是預測誤差,預測誤差是自回歸預測和真實值之間的偏差。定階過程類似AR階數的設定過程。這裏可以選擇3,或者保守點選擇2。

    信息準則定階

    • AIC(Akaike Information Criterion)

      L是數據的似然函數,k=1表示模型考慮常數c,k=0表示不考慮。最後一個1表示算上誤差項,所以其實第二項就是2乘以參數個數。

    • AICc(修正過的AIC)
    • BIC(Bayesian Information Criterion)

    注意事項:

    • 信息準則越小,說明參數的選擇越好,一般使用AICc或者BIC。
    • 差分d,不要使用信息準則來判斷,因為差分會改變了似然函數使用的數據,使得信息準則的比較失去意義,所以通常用別的方法先選擇出合適的d。
    • 信息準則的好處是可以在用模型給出預測之前,就對模型的超參做一個量化評估,這對批量預測的場景尤其有用,因為批量預測往往需要在程序執行過程中自動定階。

    構建ARIMA模型

    from statsmodels.tsa.arima_model import ARIMA
    
    # 1,1,2 ARIMA Model
    model = ARIMA(df.value, order=(1,1,2))
    model_fit = model.fit(disp=0)
    print(model_fit.summary())
    

    中間的表格列出了訓練得到的模型各項和對應的係數,如果係數很小,且‘P>|z|’ 列下的P-Value值遠大於0.05,則該項應該去掉,比如上圖中的ma部分的第二項,係數是-0.0010,P-Value值是0.998,那麼可以重建模型為ARIMA(1,1,1),從下圖可以看到,修改階數后的模型的AIC等信息準則都有所降低:

    檢查殘差

    通常會檢查模型擬合的殘差序列,即訓練數據原本的序列減去訓練數據上的擬合序列后的序列。該序列越符合隨機誤差分佈(均值為0的正態分佈),說明模型擬合的越好,否則,說明還有一些因素模型未能考慮。

    • python實現:
    # Plot residual errors
    residuals = pd.DataFrame(model_fit.resid)
    fig, ax = plt.subplots(1,2)
    residuals.plot(title="Residuals", ax=ax[0])
    residuals.plot(kind='kde', title='Density', ax=ax[1])
    plt.show()
    
    

    模型擬合

    # Actual vs Fitted
    model_fit.plot_predict(dynamic=False)
    plt.show()
    

    模型預測

    除了在訓練數據上擬合,一般都會預留一部分時間段作為模型的驗證,這部分時間段的數據不參与模型的訓練。

    from statsmodels.tsa.stattools import acf
    
    # Create Training and Test
    train = df.value[:85]
    test = df.value[85:]
    
    # Build Model
    # model = ARIMA(train, order=(3,2,1))  
    model = ARIMA(train, order=(1, 1, 1))  
    fitted = model.fit(disp=-1)  
    
    # Forecast
    fc, se, conf = fitted.forecast(15, alpha=0.05)  # 95% conf
    
    # Make as pandas series
    fc_series = pd.Series(fc, index=test.index)
    lower_series = pd.Series(conf[:, 0], index=test.index)
    upper_series = pd.Series(conf[:, 1], index=test.index)
    
    # Plot
    plt.figure(figsize=(12,5), dpi=100)
    plt.plot(train, label='training')
    plt.plot(test, label='actual')
    plt.plot(fc_series, label='forecast')
    plt.fill_between(lower_series.index, lower_series, upper_series, 
                     color='k', alpha=.15)
    plt.title('Forecast vs Actuals')
    plt.legend(loc='upper left', fontsize=8)
    plt.show()
    

    這是在ARIMA(1,1,1)下的預測結果,給出了一定的序列變化方向,看上去還是可以的。不過所有的預測值,都在真實值以下,所以還可以試試看有沒有別的更好的階數組合。
    其實如果嘗試用ARIMA(3,2,1)會發現預測的更好:

    AUTO ARIMA

    通過預測結果來推斷模型階數的好壞畢竟還是耗時耗力了些,一般可以通過計算AIC或BIC的方式來找出更好的階數組合。pmdarima模塊的auto_arima方法就可以讓我們指定一個階數上限和信息準則計算方法,從而找到信息準則最小的階數組合。

    from statsmodels.tsa.arima_model import ARIMA
    import pmdarima as pm
    
    df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/wwwusage.csv', names=['value'], header=0)
    
    model = pm.auto_arima(df.value, start_p=1, start_q=1,
                          information_criterion='aic',
                          test='adf',       # use adftest to find optimal 'd'
                          max_p=3, max_q=3, # maximum p and q
                          m=1,              # frequency of series
                          d=None,           # let model determine 'd'
                          seasonal=False,   # No Seasonality
                          start_P=0, 
                          D=0, 
                          trace=True,
                          error_action='ignore',  
                          suppress_warnings=True, 
                          stepwise=True)
    
    print(model.summary())
    
    # Forecast
    n_periods = 24
    fc, confint = model.predict(n_periods=n_periods, return_conf_int=True)
    index_of_fc = np.arange(len(df.value), len(df.value)+n_periods)
    
    # make series for plotting purpose
    fc_series = pd.Series(fc, index=index_of_fc)
    lower_series = pd.Series(confint[:, 0], index=index_of_fc)
    upper_series = pd.Series(confint[:, 1], index=index_of_fc)
    
    # Plot
    plt.plot(df.value)
    plt.plot(fc_series, color='darkgreen')
    plt.fill_between(lower_series.index, 
                     lower_series, 
                     upper_series, 
                     color='k', alpha=.15)
    
    plt.title("Final Forecast of WWW Usage")
    plt.show()
    

    從輸出可以看到,模型採用了ARIMA(3,2,1)的組合來預測,因為該組合計算出的AIC最小。

    如何自動構建季節性ARIMA模型?

    如果模型帶有季節性,則除了p,d,q以外,模型還需要引入季節性部分:

    與非季節性模型的區別在於,季節性模型都是以m為固定周期來做計算的,比如D就是季節性差分,是用當前值減去上一個季節周期的值,P和Q和非季節性的p,q的區別也是在於前者是以季節窗口為單位,而後者是連續時間的。
    上節介紹的auto arima的代碼中,seasonal參數設為了false,構建季節性模型的時候,把該參數置為True,然後對應的P,D,Q,m參數即可,代碼如下:

    # !pip3 install pyramid-arima
    import pmdarima as pm
    # Seasonal - fit stepwise auto-ARIMA
    smodel = pm.auto_arima(data, start_p=1, start_q=1,
                             test='adf',
                             max_p=3, max_q=3, m=12,
                             start_P=0, seasonal=True,
                             d=None, D=1, trace=True,
                             error_action='ignore',  
                             suppress_warnings=True, 
                             stepwise=True)
    smodel.summary()
    

    注意這裏的stepwise參數,默認值就是True,表示用stepwise algorithm來選擇最佳的參數組合,會比計算所有的參數組合要快很多,而且幾乎不會過擬合,當然也有可能忽略了最優的組合參數。所以如果你想讓模型自動計算所有的參數組合,然後選擇最優的,可以將stepwise設為False。

    如何在預測中引入其它相關的變量?

    在時間序列模型中,還可以引入其它相關的變量,這些變量稱為exogenous variable(外生變量,或自變量),比如對於季節性的預測,除了之前說的通過加入季節性參數組合以外,還可以通過ARIMA模型加外生變量來實現,那麼這裏要加的外生變量自然就是時間序列中的季節性序列了(通過時間序列分解得到)。需要注意的是,對於季節性來說,還是用季節性模型來擬合比較合適,這裏用外生變量的方式只是為了方便演示外生變量的用法。因為對於引入了外生變量的時間序列模型來說,在預測未來的值的時候,也要對外生變量進行預測的,而用季節性做外生變量的方便演示之處在於,季節性每期都一樣的,比如年季節性,所以直接複製到3年就可以作為未來3年的季節外生變量序列了。

    
    def load_data():
        """
        航司乘客數時間序列數據集
        該數據集包含了1949-1960年每個月國際航班的乘客總數。
        """
        from datetime import datetime
        date_parse = lambda x: datetime.strptime(x, '%Y-%m-%d')
        data = pd.read_csv('https://www.analyticsvidhya.com/wp-content/uploads/2016/02/AirPassengers.csv', index_col='Month', parse_dates=['Month'], date_parser=date_parse)
        # print(data)
        # print(data.index)
        ts = data['value']
        # print(ts.head(10))
        # plt.plot(ts)
        # plt.show()
        return ts,data
    
    # 加載時間序列數據
    _ts,_data = load_data()
    # 時間序列分解
    result_mul = seasonal_decompose(_ts[-36:],  # 3 years
                                    model='multiplicative',
                                    freq=12,
                                    extrapolate_trend='freq')
    _seasonal_frame = result_mul.seasonal[-12:].to_frame()
    _seasonal_frame['month'] = pd.to_datetime(_seasonal_frame.index).month
    # seasonal_index = result_mul.seasonal[-12:].index
    # seasonal_index['month'] = seasonal_index.month.values
    print(_seasonal_frame)
    _data['month'] = _data.index.month
    print(_data)
    _df = pd.merge(_data, _seasonal_frame, how='left', on='month')
    _df.columns = ['value', 'month', 'seasonal_index']
    print(_df)
    print(_df.index)
    _df.index = _data.index  # reassign the index.
    print(_df.index)
    
    build_arima(_df,_seasonal_frame,_data)
    
    # SARIMAX Model
    sxmodel = pm.auto_arima(df[['value']],
    						exogenous=df[['seasonal_index']],
    						start_p=1, start_q=1,
    						test='adf',
    						max_p=3, max_q=3, m=12,
    						start_P=0, seasonal=False,
    						d=1, D=1, trace=True,
    						error_action='ignore',
    						suppress_warnings=True,
    						stepwise=True)
    sxmodel.summary()
    # Forecast
    n_periods = 36
    fitted, confint = sxmodel.predict(n_periods=n_periods,
    								  exogenous=np.tile(seasonal_frame['y'].values, 3).reshape(-1, 1),
    								  return_conf_int=True)
    index_of_fc = pd.date_range(data.index[-1], periods = n_periods, freq='MS')
    # make series for plotting purpose
    fitted_series = pd.Series(fitted, index=index_of_fc)
    lower_series = pd.Series(confint[:, 0], index=index_of_fc)
    upper_series = pd.Series(confint[:, 1], index=index_of_fc)
    
    # Plot
    plt.plot(data['y'])
    plt.plot(fitted_series, color='darkgreen')
    plt.fill_between(lower_series.index,
    				 lower_series,
    				 upper_series,
    				 color='k', alpha=.15)
    
    plt.title("SARIMAX Forecast of a10 - Drug Sales")
    plt.show()
    
    

    以下是結果比較:

    • 選擇ARIMA(3,1,1)來預測:
    • 選擇季節性模型SARIMA(3,0,1),(0,1,0,12)來預測:
    • 選擇帶季節性外生變量的ARIMA(3,1,1)來預測:

    ok,本篇就這麼多內容啦~,下一篇將基於一個實際的例子來介紹完整的預測實現過程,感謝閱讀O(∩_∩)O。

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

    【其他文章推薦】

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

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

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

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

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

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

  • Jmeter(十) – 從入門到精通 – JMeter邏輯控制器 – 中篇(詳解教程)

    Jmeter(十) – 從入門到精通 – JMeter邏輯控制器 – 中篇(詳解教程)

    1.簡介

    Jmeter官網對邏輯控制器的解釋是:“Logic Controllers determine the order in which Samplers are processed.”。

    意思是說,邏輯控制器可以控制採樣器(samplers)的執行順序。由此可知,控制器需要和採樣器一起使用,否則控制器就沒有什麼意義了。放在控制器下面的所有的採樣器都會當做一個整體,執行時也會一起被執行。

    JMeter邏輯控制器可以對元件的執行邏輯進行控制,除僅一次控制器外,其他可以嵌套別的種類的邏輯控制器。

    2.邏輯控制器分類

    JMeter中的Logic Controller分為兩類:
    (1)控制測試計劃執行過程中節點的邏輯執行順序,如:Loop Controller、If Controller等;
    (2)對測試計劃中的腳本進行分組、方便JMeter統計執行結果以及進行腳本的運行時控制等,如:Throughput Controller、Transaction Controller。

    3.預覽邏輯控制器 

    首先我們來看一下JMeter的邏輯控制器,路徑:線程組(用戶)->添加->邏輯控制器(Logic Controller);我們可以清楚地看到JMeter5中共有17個邏輯控制器,如下圖所示:

    如果上圖您看得不是很清楚的話,宏哥總結了一個思維導圖,關於JMeter5的邏輯控制器類型,如下圖所示: 

     通過以上的了解,我們對邏輯控制器有了一個大致的了解和認識。下面宏哥就給小夥伴或則童鞋們分享講解一些通常在工作中會用到的邏輯控制器。 

    4.常用邏輯控制器詳解

      這一小節,宏哥就由上而下地詳細地講解一下常用的邏輯控制器。

    4.1Critical Section Controller

    我們先來看一下,官方原汁原味的解釋:The Critical Section Controller ensures that its children elements (samplers/controllers, etc.) will be executed by only one thread as a named lock will be taken before executing children of controller.

    宏哥這個二把刀的翻譯,給你們翻譯一下這段鳥語看看到底是什麼意思,大致意思是: Critical Section Controller(臨界區控制器),確保它的子元素(samplers /控制器等)在執行控制器的子程序之前只執行一個線程作為指定的鎖。呵呵!看到這句話是不是覺得一頭霧水啊,摸一摸自己所剩無幾的頭髮陷入沉思中…..沒有關係的,不要糾結了,宏哥後邊會用具體實例講解一下,看完實例后,再回過頭來閱讀這句話,你就會恍然大悟了。

     1、我們先來看看這個Critical Section Controller長得是啥樣子,路徑:線程組 > 添加 > 邏輯控制器 > 臨界部分控制器,如下圖所示:

    2、關鍵參數說明如下:

    Name:名稱,可以隨意設置,甚至為空;

    Comments:註釋,可隨意設置,可以為空;

    Lock name:鎖名稱,這裏可以填入其子節點下執行的線程的名稱,這個線程作為一個全局鎖存在

    4.1.1實例講解 

    這部分主要是通過配合實例我們來理解一下開始那句話到底什麼意思。

    1、宏哥這裏先說一個訪問宏哥博客園的JMeter系列文章的測試場景:我們第一步首先要訪問博客園的首頁,第二步找到宏哥的訪問宏哥博客園的首頁,第三步點擊JMeter類別。按順序完成三步,才能完成這個測試場景。那麼我們根據這個場景用JMeter來添加多個請求的取樣器。如下圖所示:

    2、腳本調試是通了,運行JMeter,查看結果樹,如下圖所示:

    3、從上個圖,查看結果樹中显示請求結果數據不是按照順序請求,不符合預期,這個時候增加一個critical section controller(臨界部分控制器),增加一個鎖,就能控制執行順序。如下圖所示:

    4、腳本調試是通了,運行JMeter,查看結果樹,可以清楚地看出來是按預期的順序執行請求的。但是這樣響應時間會過長,這個後邊再做講解。如下圖所示: 

     4.1.2鎖名分類

    (1)鎖名為空,認為每個鎖為不同的鎖

    1、宏哥通過具體實例,來看一下,創建鎖名為空的臨界部分控制器,如下圖所示:

    2、運行JMeter,查看結果樹,如下圖所示:

    (2)鎖名相同,多個鎖認為是同一個鎖,同一個時間點只能存在一個運行中

    1、宏哥通過具體實例,來看一下,創建鎖名相同的臨界部分控制器,如下圖所示:

    2、運行JMeter,查看結果樹,如下圖所示:

    (3)鎖名為變量,根據變量值來判斷是不是屬於同一個鎖,變量值為相同時,則認為是同一個鎖

    1、宏哥通過具體實例,來看一下,創建鎖名為變量的臨界部分控制器,如下圖所示:

    2、運行JMeter,查看結果樹,如下圖所示:

    4.2ForEach Controller

    ForEach 控制器:一般搭配用戶變量使用。依次調用用戶定義的變量,直到最後一個,結束循環。為了滿足ForEach Controller提取數據,變量命名的格式一般為“變量名_数字”,其中数字從1開始。
    1、即遍歷循環控制器,顧名思義是定義一個循環規則。
    2、用來遍歷當前元素的所有可執行場景。
    3、在用戶自定義變量中讀取一系列相關的變量,該控制器下的採樣器或控制器都會被執行一次或多次,每次讀取不同的變量值。
    4、這個控制器一般配合配置元件 → 正則表達式提取器來一起使用,可對頁面上的某些元素進行重複處理。

    1、我們先來看看這個ForEach Controller長得是啥樣子,路徑:線程組 > 添加 > 邏輯控制器 > ForEach控制器,如下圖所示: 

    2、關鍵參數說明如下:

    Name:名稱,可以隨意設置,甚至為空;

    Comments:註釋,可隨意設置,可以為空;

    Input variable prefix:輸入變量前綴,可以在“用戶自定義變量”中定義一組變量,循環控制器可以從中獲取到變量對應的值,然後作為循環控制器的循環條件,還可以輸出變量作為取樣器的參數。

    Start index for loop:循環變量下標起點。循環指數開始(唯一)→ 遍歷查詢的變量範圍,開始的值(這裏如果不填寫,默認從 1 開始,如果沒有 1 開始的變量,執行時會報錯)

    End index for loop:循環變量下標終點。循環指數結束(包含)→ 遍歷查詢的變量範圍,結束的值

    Output variable name:輸出變量名稱,循環控制器生成的變量名稱。後續可通過${}引用

    Add “_” before number ?: 變量前綴后是否加“_”作為分隔符。如果定義的變量名中有下劃線的話就要勾選此項,否則找不到;反之,沒有的話不要勾選,否則同樣找不到變量

    4.2.1實例講解

    1、首先在自定義5個前綴為 北京宏哥 的變量,值分別為 a b c d e。並且 北京宏哥 後面的数字是連續的,如果不連續,則不會被循環到,如下圖所示:

    2、配置ForEach控制器,如下圖所示:

    3、添加請求 訪問博客園首頁 + 輸出值:${宏哥},輸出值是在控制器的輸出變量 宏哥,通過 ${宏哥} 取到輸出變量的值,如下圖所示:

    4、添加查看結果樹,運行JMeter,查看結果樹,如下圖所示: 

    注意:敲黑板,敲腦袋!!!

    1、輸入變量的後綴數值一定要連續,比如 北京宏哥_1, 北京宏哥_2, 北京宏哥_3 … 這樣,如果中間有不連續的,循環會中斷

    2、循環開始的設定:如果變量為北京宏哥_1, 北京宏哥_2, 北京宏哥_3,而設定的開始為 1,則會從北京宏哥_2 開始循環

    3、循環結束的設定:如果變量有3個 北京宏哥_1, 北京宏哥_2, 北京宏哥_3,而設定的結束為5,則只會循環 北京宏哥_1, 北京宏哥_2, 北京宏哥_3 ,如果設定的結束為2,則會循環  北京宏哥_1, 北京宏哥_2 。

    4.3Include Controller

    Include控制器用來導入外部的測試片段(非完整的測試計劃),在執行時會執行導入的測試計劃,但是被導入的測試計劃有特殊要求,它不能有線程組,只能包含簡單的控制器及控制器下的元件。換句話說就是相當於加了一個執行單元,一個封裝了的業務操作單元,類似我們程序開發中的函數(方法)一樣。例如一個查詢學生信息的業務操作我們用取樣器來模擬,然後放到簡單控制器中作為一個執行單元,別的地方也要用到時,我們可以不用重複造輪子直接引用過來。

    一般來說,Include控制器和測試片段(Test Fragment)配合使用的比較常見。

    1、我們先來看看這個include Controller長得是啥樣子,路徑:線程組 > 添加 > 邏輯控制器 > Include控制器,如下圖所示:

    2、關鍵參數說明如下:

    Name:名稱,可以隨意設置,甚至為空;

    Comments:註釋,可隨意設置,可以為空;

    Filename:文件名,必輸字段,如果沒有,就會報錯。通過Filename的路徑和文件名引用外部的jmx文件。

    宏哥推薦小夥伴或者童鞋們可以將 Include控制器 Module控制器(傳送門)一起對比着學習,Include控制器 是從外部文件引用,只能引用整個測試片段的內容,Module控制器 是從內部文件中引用,引用上相對比較靈活,可以只引用部分測試片段或模塊內容。這樣一內一外不僅容易理解也容易記憶和學習。

    4.3.1實例

    (1)當Filename路徑的值為空,程序執行報錯,腳本執行中止,不會繼續執行下面的腳本內容。

    1、首先創建一個Filename路徑為空的測試計劃,如下圖所示:

    2、運行JMeter,查看結果樹(程序執行報錯,腳本執行中止,不會繼續執行下面 訪問博客園首頁 的取樣器),如下圖所示: 

    (2)當Filename路徑中的文件不存在,程序直接彈窗報錯並停止執行。

    1、首先創建一個Filename路徑中的文件不存在的測試計劃,點擊“保存”按鈕的時候,就會直接彈窗報錯。如下圖所示:

    (3)當Filename路徑的文件中不包含測試片段,跳過控制器,繼續向下執行。

    1、首先創建一個外部引用沒有測試片段的測試計劃,如下圖所示:

    2、創建一個Filename路徑的文件中不包含測試片段的測試計劃,將上邊的外部引用-無測試片段文件添加到Include控制器中,如下圖所示:

    3、運行JMeter,查看結果樹(跳過控制器,繼續向下執行 訪問博客園首頁 的取樣器),如下圖所示: 

    (3)當Filename路徑的文件中包含測試片段,執行完控制器,再繼續向下執行。

    1、首先創建一個外部引用有測試片段的測試計劃,如下圖所示:

    2、創建一個Filename路徑的文件中包含測試片段的測試計劃,將上邊的外部引用-有測試片段文件添加到Include控制器中,如下圖所示:

    3、運行JMeter,查看結果樹(執行完控制器里的測試片段,再繼續向下執行 訪問博客園首頁 的取樣器),如下圖所示: 

    到這裏,大家應該理解了  Include Controller 和  Test Fragment 了吧。宏哥的理解就是,Test Fragment 相當於一個獨立的部分,可以被其他測試計劃引用,實現 樣例的片段化,模塊化,遇到重複需要的,比如登錄、註冊之類的,就可以用Test FragmentInclude Controller 了。這樣可以避免重複造輪子,做許多無用功。

    5.小結

       好了,今天關於邏輯控制器的上篇就講解到這裏,這一篇主要介紹了 Critical Section ControllerForEach ControllerInclude控制器

     

    您的肯定就是我進步的動力。如果你感覺還不錯,就請鼓勵一下吧!記得隨手點波  推薦  不要忘記哦!!!

    別忘了點 推薦 留下您來過的痕迹

     

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

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    台北網頁設計公司這麼多該如何選擇?

    ※智慧手機時代的來臨,RWD網頁設計為架站首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※回頭車貨運收費標準