Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expander ライブラリを作成 #50

Closed
wants to merge 13 commits into from
Closed

Expander ライブラリを作成 #50

wants to merge 13 commits into from

Conversation

kzrnm
Copy link
Owner

@kzrnm kzrnm commented Sep 15, 2020

Expander の実装方法をいろいろ検討して、C# のみで完結してなおかつオーバーヘッドが小さい手法を思いついたので作成してみました。

  • GitHub Actions によるソースコード埋め込み
  • 埋め込んだソースコードを利用するライブラリ

の2つの機能にわかれているのでそれぞれ説明します。

GitHub Actions によるソースコード埋め込み

SourceCodeEmbeder を GitHub Actions で実行して、AtCoderLibrary にソースコード埋め込みファイルを自動コミットします。

ソースコード埋め込み用の型には EditorBrowsable(EditorBrowsableState.Never) をつけているので通常のライブラリ利用者からは見れません。

SourceCodeEmbeder が行うこと

  • ソースコードの埋め込み
    • using ディレクティブとその他のコードの分離
    • Trivia (Roslyn の用語) をすべて単一のスペースに置換することでコードを圧縮
  • ファイル内で定義されている型の解析・埋め込み
  • ソース間の依存関係の解析・埋め込み

GitHub Actions の実行例

https://github.com/naminodarie/ac-library-cs/actions/runs/255529330

埋め込んだソースコードを利用するライブラリ

Expander が埋め込んだソースコードを展開するライブラリです。

README を書いてます。

https://github.com/naminodarie/ac-library-cs/blob/expander_cs/AtCoderLibrary.Expander/README.md

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using AtCoder;
using FenwickTree = AtCoder.IntFenwickTree;

class Program
{
    static void Main(string[] args)
    {
        var expandMethod = ExpandMethod.All;
        //var expandMethod = ExpandMethod.NameSyntax;
        //var expandMethod = ExpandMethod.Strict;
        Console.WriteLine(expandMethod);
        var sw = Stopwatch.StartNew();

        Expander.Expand(expandMethod: expandMethod);
        Console.WriteLine($"expand time: {sw.ElapsedMilliseconds} ms");
        var fw = new FenwickTree(5);
        for (int i = 0; i < 5; i++) fw.Add(i, i + 1);
        Console.WriteLine(fw.Sum(0, 5));
        Console.WriteLine($"finish time: {sw.ElapsedMilliseconds} ms");
    }
}

struct Monoid : IMonoidOperator<int>
{
    public int Identity => 0;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int Operate(int x, int y) => x + y;
}
class Segtree : Segtree<int, Monoid> { public Segtree(int n) : base(n) { } }

上記のようなファイルでためしたところ実行時間はそれぞれ

ExpandMethod expand time (ms)
All 40 ms
NameSyntax 300 ms
Strict 1200 ms

程度となりました。

#21

@key-moon
Copy link
Contributor

かなり本家と毛色が違う Expand 方法なので、これがどのようにコミュニティに受け入れられるかは分からないため議論無しで自信を持ってマージすることができません。

個人的には、便利ではあるが少し自由が効かない方法だという印象を持ちました。毎デバッグの際にこれが実行されるのはあまり嬉しくはなさそうです。

コードベースとして依存フロー解析のコードはとても助かります。GitHub Actionでフロー解析を前処理しておくのは合理的ですし、Expander 自体に埋め込んでしまえば余計なファイルも気になりませんね。 #21 に今までの話を追記しておくので、検討段階での試案や採用しなかった理由/デメリットについても書いて頂けると助かります。

@kzrnm
Copy link
Owner Author

kzrnm commented Sep 15, 2020

毎デバッグの際にこれが実行されるのはあまり嬉しくはなさそうです。

そう思いまして、Combined.csx にタイムスタンプを埋め込む機能を一応作っています。

Program.cs にこっそり書いてるのですが、

// do nothing if file is not updated.
Expander.Expand(checkLastWriteTime: true);

とすると $"Last: {ファイルの更新日時.Ticks}"Combined.csx の先頭に埋め込まれて、更新されていなかったら何もせずに終了します。

@kzrnm kzrnm mentioned this pull request Sep 15, 2020
@kzrnm
Copy link
Owner Author

kzrnm commented Sep 15, 2020

#21 に検討した内容を書き連ねました。

@kzrnm
Copy link
Owner Author

kzrnm commented Sep 15, 2020

ファイルの中から直接呼び出すのではなくPowerShellから呼び出すサンプルを追加しました。

@kzrnm
Copy link
Owner Author

kzrnm commented Sep 19, 2020

master を取り込みました。

@kzrnm
Copy link
Owner Author

kzrnm commented Sep 19, 2020

Expander はCC0にしたくないので一旦閉じます。

@kzrnm kzrnm closed this Sep 19, 2020
@kzrnm kzrnm reopened this Sep 19, 2020
@kzrnm kzrnm closed this Sep 19, 2020
@kzrnm kzrnm mentioned this pull request Sep 19, 2020
kzrnm added a commit that referenced this pull request Feb 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants