2017-08-14 6 views
-4

私のテストが間違っていない限り、プレーン関数の使用を含む他のすべてのオプションは、埋め込みエイリアスを使用して別のパッケージのメソッドを定義するよりも約35%長くなります。私はおそらく何か間違ったことをしていて、それが何であるかを知りたいです。詳細はthis repositoryを参照してください。埋め込みエイリアスを使用して、異なるパッケージ内の構造体のメソッドを効率的に定義していますか?

[編集]コメント/提案ありがとうございました。以下は、「メソッド」と「meth」の比較に関連するコードのみを示しています。前者は、構造体とともにモデルパッケージで定義された典型的なメソッドを使用します。 "meth"オプションは、datactrlパッケージで定義された埋め込みエイリアスを使用するメソッドを定義します。最初のコード例には、構造体定義と、テストで使用される構造体のエクスポートされたデフォルトインスタンスが含まれています。パッケージモデルから

、ファイルmodels.go

type CmntData struct { 
    ID   int 
    Slug  string 
    Title  string 
    PageID  int 
    Text  string 
    DateCreated time.Time 
    CreatedBy int 
} 

var DefaultCD = CmntData{ID: 100, Title: "Demo Comment", 
Text: "This is a test comment", PageID: 1000, CreatedBy: 4242} 


// Local methods called by the "method" test 

func (cd *CmntData) NewComment(ncd CmntData) *CmntData { 

    ncd.DateCreated = time.Now() 

    return &ncd 
} 

func (cd *CmntData) DefaultComment(cnt int) *CmntData { 

    dcd := DefaultCD 
    dcd.Slug = "demo-comment-" + strconv.Itoa(cnt + 1) 

    return cd.NewComment(dcd) 
} 

パッケージdatactrlから、パッケージのメインからcomments.go

// Types and method definitions used to add methods to models.CmntData 

type roCmntData struct { 
    ModelCD models.CmntData 
} 

type roCD struct{} 

// roComment allows us to effectively add methods to models.CmntData. 
// Data and "local" methods defined for models.CmntData are accessible. 
type roComment struct { 
    *roCmntData // Provides access to models.CmntData 
    *roCD  // Required to make the magic happen 
} 

// Other packages must use Rcd to access methods added to models.CmntData 
var Rcd = roComment { 
    roCmntData: &roCmntData{}, 
    roCD: &roCD{}, 
} 

// Remote methods called by the "meth" test 

func (cd *roComment) NewComment(ncd models.CmntData) *models.CmntData { 

    cd.roCmntData.ModelCD = ncd 
    cd.ModelCD.DateCreated = time.Now() 

    return &cd.ModelCD 
} 

func (cd *roComment) DefaultComment(cnt int) *models.CmntData { 

    dcd := models.DefaultCD 
    dcd.Slug = "demo-comment-" + strconv.Itoa(cnt + 1) 

    return cd.NewComment(dcd) 
} 

ファイル、ファイルmain.go

if cmd == "method" { 
    tstart := time.Now() 
    dcd := models.CmntData{} 
    for i := 0; i < limit; i++ { 
     defCD = dcd.DefaultComment(i) 
    } 
    tfinish := time.Now() 
    elapsed = tfinish.Sub(tstart) 
} 

if cmd == "meth" { 
    tstart := time.Now() 

    // datactrl.Rcd provides access to remote models.CmntData methods 
    dcd := &datactrl.Rcd 
    for i := 0; i < limit; i++ { 
     defCD = dcd.DefaultComment(i) 
    } 
    tfinish := time.Now() 
    elapsed = tfinish.Sub(tstart) 
} 

Screen shot of resultsは平均40回のループをとり、各ループは100万回のテスト実行の平均を返します。記録のために、 "func"と "function"の両方のテストは、 "method"によって投稿された結果の2ms以内に完了します。

+0

あなたのコードから見えるものは何ですか? 4つの事柄はすべてほぼ同じ時間に実行されます。 – zerkms

+3

あなたはコードを最小限の問題と共有を説明するために必要なものに変換することができますか?https://play.golang.orgになるでしょう –

+2

解体を見てみましたか?また、あなたのメソッドは、ポインタ受信機を取る、関数は値の引数を取る。このメソッドはポインタを渡し、関数は完全なオブジェクトに渡されます。コンパイラがその違いを最適化しない限り(これはそうではないと思われます)、それはパフォーマンスの違いを説明します –

答えて

-1

実際に@JimBが私の質問に答えましたが、質問に関するコメントにあります。

答えは、それらが含まれる構造体と同じパッケージで定義されている典型的なメソッドは、余分なメモリ割り当てが必要であると思われます。私がリモートメソッド定義と呼ばれた結果、小さなエッジが得られます。

何が起こっているのかを明確にするために多くのコメントを必要とする何かを行うことは価値がないかもしれないことに注意してください。一方、データ操作とデータ定義を分離する必要がある場合は、リモートメソッドを使用して、追加のボーナスとして数秒ごとに数マイクロセカンドを保存します。 :)

GoのBenchmark機能を使用するための彼の提案は、テストで構築され、良いもののように聞こえる。私はそれを自分で調べていきます。

+0

'メソッドは、それらが含まれる構造体と同じパッケージに定義されているため、余分なメモリ割り当てが必要です.' - それは余分な割り当ての理由ではありません。 "メソッド"テスト​​は毎回新しい値を作成し、 "meth"テストは毎回 'Rcd'にあらかじめ割り当てられた同じ場所に値を書き込みます。それぞれのケースでリターンポインタのアドレスを調べることでこれをテストできます。興味深いもの: – JimB

+0

それは、理論的には、「方法」が同じことをするために修正されることを意味しますか?実際、 "meth"の値は、別のパッケージに定義されている構造体のメソッドを定義することができます。メソッドコールがとても速いので、時間を25%削減することは重要ではないことが分かりました。問題を調べる時間をとってくれてありがとう。 – emadera52

関連する問題