Movatterモバイル変換


[0]ホーム

URL:


Yoshifumi Kawai, profile picture
Uploaded byYoshifumi Kawai
PDF, PPTX76,946 views

CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する

Talked at CEDEC 2018, 2018/08/22 - https://2018.cedec.cesa.or.jp/session/detail/s5b559852a6405

Embed presentation

Download as PDF, PPTX
Tweetは是非 #CEDEC2018スライドはセッション後すぐ公開します
河合 宜文 / Kawai Yoshifumi / @neueccNew World, Inc.C#Unity
C#最速シリアライザhttps://github.com/neuecc/MessagePack-CSharp/
Reactive Extensions for Unityhttps://github.com/neuecc/UniRx/async/await(UniTask)async UniTask<string> DemoAsync(){// You can await Unity's AsyncObjectvar asset = await Resources.LoadAsync<TextAsset>("foo");// .ConfigureAwait accepts progress callbackawait SceneManager.LoadSceneAsync("scene2").ConfigureAwai// await frame-based operation(you can also await frame cawait UniTask.Delay(TimeSpan.FromSeconds(3));// like 'yield return WaitForEndOfFrame', or Rx's Observeawait UniTask.Yield(PlayerLoopTiming.PostLateUpdate);// You can await standard taskawait Task.Run(() => 100);// get async webrequestasync UniTask<string> GetTextAsync(UnityWebRequest req){var op = await req.SendWebRequest();return op.downloadHandler.text;}var task1 = GetTextAsync(UnityWebRequest.Get("http://googvar task2 = GetTextAsync(UnityWebRequest.Get("http://bingvar task3 = GetTextAsync(UnityWebRequest.Get("http://yaho// concurrent async-wait and get result easily by tuple svar (google, bing, yahoo) = await UniTask.WhenAll(task1,// You can handle timeout easilyawait GetTextAsync(UnityWebRequest.Get("http://unity.com"
using C
in 10 years
C#大統一理論 #とは
サーバーもクライアントも全部C#で統一する
サーバーサイドエンジニアでC#で書ける人間がいなくて覚えなおし基盤システムがもう構築されてるコードが流用できないそもそもWindowsだしいやMicrosoftがいや余計にお金がかかりそうプロプライエタリじゃないのGoのほうがなうい別にPHPで困ってないC++のほうがパフォーマンスいいんじゃないのノウハウがないインターネットに情報がないオープンじゃない気がするMacで動かないんじゃないの事例もあんまないし失敗しそうetc...
サーバーサイドエンジニアでC#で書ける人間がいなくて覚えなおし基盤システムがもう構築されてるコードが流用できないそもそもWindowsだしいやMicrosoftがいや余計にお金がかかりそうプロプライエタリじゃないのGoのほうがなうい別にPHPで困ってないC++のほうがパフォーマンスいいんじゃないのノウハウがないインターネットに情報がないオープンじゃない気がするMacで動かないんじゃないの事例もあんまないし失敗しそうetc...
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
RealtimeUnityAPIService
Performance of C#
速い?遅い?
速い?遅い?
やっぱ遅かった。当時(15年前)パフォーマンスを志向してこなかった
Motivation
Performance by DefaultというUnityの標語ECS + Job System + Burst Compilerで、C#をC++よりも高速に性能の向上は不可能を可能にする!C# 7.x + .NET Core 2.1Linuxで動く.NET実装(登場からかなり時間も経ち十分現実的です)OSS化により細かい性能向上PRを受け入れ、人海戦術でボトルネックが潰されていっている言語やランタイムにも手を入れ大きな性能向上を果たしている
リアルな性能は基盤だけでは決まらないウェブフレームワークやデータベースアクセス、シリアライゼーション、etc...(そもそも言語自体の評価が、言語だけではなくライブラリやエコシステムなども含めて評価すべき)現実的にはまだC#はよくなってきたとはいえ、手薄そこがパフォーマンスを当初からしっかり意識して鍛え上げられてきた言語と、最近やっと目覚めたゆとりC#との違いだからこそ、やらなければならない
C#最速JSONシリアライザhttps://github.com/neuecc/Utf8Json
C#も誕生15年、一見枯れてるように見える、が別にそんなことはなかったC#で真の意味でのパフォーマンスが意識されだしたのは近年言語のポテンシャルを100%活かしたライブラリを開発することによって、C#のパフォーマンスを下支えするそして性能のベースラインを掲示したことにより、世界中でシリアライザに限らずC#のパフォーマンスへの意識を変えた常に前線で競える言語となるために誰かがやってくれるのではなく誰もが当事者それがオープンであるということだし、C#もそういう世界にいる
Introduction to theHigh Performance C#
NOTICEこの先の内容はあくまでエクストリームなパフォーマンスを求めたい場合のためであり普通に書く場合これらに気をつける必要は別に特に全くあまりないことも多いことは前提としてください
徹頭徹尾、遅くなる要因を取り除く極限的な領域だとプロファイラは役に立たない(ぶっちゃけ見ても特に何もネックになっていない)理論的に最速になるコードのイメージを描いて、全ての言語知識を駆使して通過するコードパスから無駄を省き、それに近づける狂気に彩られた執念で全てを潰す特別なことはないし一つ一つはとにかく地味それを死ぬほど徹底する、それが唯一最大の秘訣で、難しいこと
例えばint(999)をbyte[]にシリアライズvar bytes = BitConverter.GetBytes(999);unsafe{var bytes = new byte[4];fixed (byte* ptr = bytes){*((int*)ptr) = 999;}}
// ふつーのシリアライザのAPIの例byte[] Serialize<T>(T obj){// 1. 内部での書き込みストリーム作りのためにnew MemoryStreamusing(var stream = new MemoryStream())// 2. データ生成時の内部ステートを保持するためのWriterのnewvar writer = new XxxWriter(stream);// 3. Int用子シリアライザの取得あるいはprimitiveの場合はswitchvar serializer = serializerCacheDictionary[typeof(T)];// 4. (意外と内部では入ってることがある)objectへのボクシングserializer.WriteObject(writer, (object)obj);// 5. 可変長整数へのエンコードif(x <10) write... else if(x < 150) write...// 6. WriteByte呼び出しの連打(内部では幾つかのifやインクリメント)stream.WriteByte(byte >> 0); stream.WriteByte(byte >> 8) ...// 7. MemoryStreamのToArrayはbyte[]コピーmemoryStream.ToArray();}
// ふつーのシリアライザのAPIの例byte[] Serialize<T>(T obj){// 1. 内部での書き込みストリーム作りのためにnew MemoryStreamusing(var stream = new MemoryStream())// 2. データ生成時の内部ステートを保持するためのWriterのnewvar writer = new XxxWriter(stream);// 3. Int用子シリアライザの取得あるいはprimitiveの場合はswitchvar serializer = serializerCacheDictionary[typeof(T)];// 4. (意外と内部では入ってることがある)objectへのボクシングserializer.WriteObject(writer, (object)obj);// 5. 可変長整数へのエンコードif(x <10) write... else if(x < 150) write...// 6. WriteByte呼び出しの連打(内部では幾つかのifやインクリメント)stream.WriteByte(byte >> 0); stream.WriteByte(byte >> 8) ...// 7. MemoryStreamのToArrayはbyte[]コピーmemoryStream.ToArray();}そりゃ遅い!けれどそれは言われてみれば……というのも事実そして逆に言えばこれを全部避ければ速いはず!
// こんなクラスがあるとしてpublic class Sample{public int Id { get; set; }public string Name { get; set; }public string[] Addresses { get; set; }}// Object作ってSample obj = new Sample{Id = 10,Name = "Foo",Addresses = new[] { "Foo", "Bar", "Baz" }};// こんな感じにbyte[]に変換するというAPIbyte[] bin = MessagePackSerializer.Serialize<Sample>(obj);
// これを詳細にバラすとbyte[] bin = MessagePackSerializer.Serialize<Sample>(obj);// Sampleの子シリアライザを取得しvar sampleFormatter = StandardResolver.Instance.GetFormatter<Sample>();// resultの参照byte[] bin = null;// こんな風になっている(refによってbinに結果が詰まってくる)sampleFormatter.Serialize(ref bin, 0, obj, StandardResolver.Instance);
sampleFormatter.Serialize(ref bin, 0, obj, StandardResolver.Instance);// 子シリアライザ取得のための入れ物(後述)IFormatterResolver resolver = StandardResolver.Instance;// メモリプールから作業用byte[]を取得var bin = BufferPool.ThreadStaticBuffer;// byte[]上の0位置から書き込み開始var offset = 0;// オブジェクトの線形化 -> 配列上にならべる[Id, Name, Addresses]offset += MessagePackBinary.WriteArrayHeader(ref bin, offset, 3);// intのプリミティブバイナリ化offset += MessagePackBinary.WriteInt32(ref bin, offset, obj.Id);// stringのプリミティブバイナリ化offset += MessagePackBinary.WriteString(ref bin, offset, obj.Name);// string[]の子シリアライザを取得var addressessFormatter = resolver.GetFormatter<string[]>();offset += addressessFormatter.Serialize(ref bin, offset, obj.Addresses, resolver);// 新規にbyte[]を作り作業用byte[]からコピーvar finalBytes = new byte[offset];Buffer.BlockCopy(bin, 0, finalBytes, 0, offset);return finalBytes;
sampleFormatter.Serialize(ref bin, 0, obj, StandardResolver.Instance);// 子シリアライザ取得のための入れ物(後述)IFormatterResolver resolver = StandardResolver.Instance;// メモリプールから作業用byte[]を取得var bin = BufferPool.ThreadStaticBuffer;// byte[]上の0位置から書き込み開始var offset = 0;// オブジェクトの線形化 -> 配列上にならべる[Id, Name, Addresses]offset += MessagePackBinary.WriteArrayHeader(ref bin, offset, 3);// intのプリミティブバイナリ化offset += MessagePackBinary.WriteInt32(ref bin, offset, obj.Id);// stringのプリミティブバイナリ化offset += MessagePackBinary.WriteString(ref bin, offset, obj.Name);// string[]の子シリアライザを取得var addressessFormatter = resolver.GetFormatter<string[]>();offset += addressessFormatter.Serialize(ref bin, offset, obj.Addresses, resolver);// 新規にbyte[]を作り作業用byte[]からコピーvar finalBytes = new byte[offset];Buffer.BlockCopy(bin, 0, finalBytes, 0, offset);return finalBytes;
Chapter1: Dictionary Hack
取得にDictionaryはコストゼロのように使いがちMessagePack for C#では以下のように型毎のシリアライザを取得普通の作り方(?)だとこれを辞書から取ってくるDictionary(ハッシュテーブル)はO(1)つまりタダじゃん、やったー!ではないO(1)でも内部的な処理量はそこそこあり、それなりに遅い(もっといえば汎用的に使えるようになっているため、その汎用化部分がコードのパフォーマンスを若干落としてる、詳細は後述)IMessagePackFormatter<string[]> f = resolver.GetFormatter<string[]>();IMessagePackFormatter<string[]> f = dict[typeof(string[])];
取得にDictionaryはコストゼロのように使いがちMessagePack for C#では以下のように型毎のシリアライザを取得普通の作り方(?)だとこれを辞書から取ってくるDictionary(ハッシュテーブル)はO(1)つまりタダじゃん、やったー!ではないO(1)でも内部的な処理量はそこそこあり、それなりに遅い(もっといえば汎用的に使えるようになっているため、その汎用化部分がコードのパフォーマンスを若干落としてる、詳細は後述)IMessagePackFormatter<string[]> f = resolver.GetFormatter<string[]>();IMessagePackFormatter<string[]> f = dict[typeof(string[])];
public class SampleResolver : IFormatterResolver{public static readonly IFormatterResolver Instance = new SampleResolver();SampleResolver() { }public IMessagePackFormatter<T> GetFormatter<T>(){// Dictionaryのlookupのかわりに<T>.fieldから取ってくる// 処理効率はJITコンパイラに委ねられ、C#のレイヤーでどうこうするより圧倒的に速いreturn Cache<T>.formatter;}static class Cache<T>{public static readonly IMessagePackFormatter<T> formatter;// 静的コンストラクタはスレッドセーフで必ず一度しか呼ばれないことが言語的に保証されているstatic Cache(){var t = typeof(T);if (t == typeof(int)) formatter = new Int32Formatter();else if (t == typeof(string)) formatter = new NullableStringFormatter();else ....}}}
public class SampleResolver : IFormatterResolver{public static readonly IFormatterResolver Instance = new SampleResolver();SampleResolver() { }public IMessagePackFormatter<T> GetFormatter<T>(){// Dictionaryのlookupのかわりに<T>.fieldから取ってくる// 処理効率はJITコンパイラに委ねられ、C#のレイヤーでどうこうするより圧倒的に速いreturn Cache<T>.formatter;}static class Cache<T>{public static readonly IMessagePackFormatter<T> formatter;// 静的コンストラクタはスレッドセーフで必ず一度しか呼ばれないことが言語的に保証されているstatic Cache(){var t = typeof(T);if (t == typeof(int)) formatter = new Int32Formatter();else if (t == typeof(string)) formatter = new NullableStringFormatter();else ....}}}
ジェネリック型はIL2CPPでコードサイズが膨らむstatic class Cache<T>{public static readonly IMessagePackFormatter<T> formatter;// この中身のコードはTが値型の場合、同じものが吐かれる(参照型ならば共有される)// 値型はPrimitiveだけじゃなくEnumなども含まれるため、場合によっては凄い量になる……static Cache(){// もしこの中身が凄い多い場合かなりのことになる// 実際UnityのIL2CPPでDictionary<TKey, TValue>はバイナリサイズが膨らむ要因の一つ!var t = typeof(T);if (t == typeof(int)) formatter = new Int32Formatter();else if (t == typeof(string)) formatter = new NullableStringFormatter();else ....}}
static class Cache<T>{public static readonly IMessagePackFormatter<T> formatter;static Cache(){var f = CacheHelper.CreateFormatter(typeof(T));if (f != null){formatter = (IMessagePackFormatter<T>)f;}}}static class CacheHelper{public static object CreateFormatter(Type t){if (t == typeof(int)) return new Int32Formatter();else if (t == typeof(string)) return new NullableStringFormatter();else ....return null;}
標準のDictionaryは決して最速ではないGetHashCode, Equalsの呼び出しがIEqualityComparer<T>経由というオーバーヘッドがかなり大きい直接呼び出しと、仮想メソッド呼び出しの性能差は確実にある辞書が必要なら型を決め打って直接呼び出しにした自家製のほうが性能面では明らかに良好キーが非ジェネリックな辞書(Dictionary<Type, ...>)や文字列(Dictionary<string, ...>バイト配列(Dictionary<byte[], ...>)相当のものはよく作り使う
標準のDictionaryは決して最速ではないGetHashCode, Equalsの呼び出しがIEqualityComparer<T>経由というオーバーヘッドがかなり大きい直接呼び出しと、仮想メソッド呼び出しの性能差は確実にある辞書が必要なら型を決め打って直接呼び出しにした自家製のほうが性能面では明らかに良好キーが非ジェネリックな辞書(Dictionary<Type, ...>)や文字列(Dictionary<string, ...>バイト配列(Dictionary<byte[], ...>)相当のものはよく作り使う
標準のDictionaryは決して最速ではないGetHashCode, Equalsの呼び出しがIEqualityComparer<T>経由というオーバーヘッドがかなり大きい直接呼び出しと、仮想メソッド呼び出しの性能差は確実にある辞書が必要なら型を決め打って直接呼び出しにした自家製のほうが性能面では明らかに良好キーが非ジェネリックな辞書(Dictionary<Type, ...>)や文字列(Dictionary<string, ...>バイト配列(Dictionary<byte[], ...>)相当のものはよく作り使う
byte[](ArraySegment<byte>) のKeyの辞書を作るKeyからValueを引くためだけにStringにデコードするのは高コストもし入力がbyte[]なら、デコードせずそのまま参照すればいい
byte[](ArraySegment<byte>) のKeyの辞書を作るKeyからValueを引くためだけにStringにデコードするのは高コストもし入力がbyte[]なら、デコードせずそのまま参照すればいいハッシュ値算出のアルゴリズムを工夫するbyte[]からハッシュ値を作るアルゴリズムは色々あるMessagePack for C#ではFarmHashを採用小さめのサイズの文字列に適しているため用途にマッチしていた一般的にはxxHashが万能に最強説があるLZ4やZStandard作者によるもの
プロパティ名のマッチングを最適化したいMessagePackのMapモード(JSONの{}とほぼ同じ)やUtf8Jsonでデシリアライズ時に、キーをどの値としてデコードすべきか名前のマッチングが必要一々デコードしてのStringがキーの辞書は論外byte[]がキーの辞書も良いけれど、この場合更に上の技法がある
文字列は重いDictionaryの仕組みとして取得時にGetHashCode -> Equalsが走るC#の文字列の中身はUTF16で、つまりbyte[]的なものGetHashCodeで全探索して算出、Equalsで全数比較文字列が長ければ長いほどインパクトがあることは頭に留めたい例えばint IDに変換して代替できるなら、そのほうがずっと良いEnumは重いEnumは実態は数値型で生で扱う場合は超軽量ですがそれ以外は重めの処理が入りがちなので注意特にUnityではDictionaryのKeyに使うとボクシングが発生……
文字列は重いDictionaryの仕組みとして取得時にGetHashCode -> Equalsが走るC#の文字列の中身はUTF16で、つまりbyte[]的なものGetHashCodeで全探索して算出、Equalsで全数比較文字列が長ければ長いほどインパクトがあることは頭に留めたい例えばint IDに変換して代替できるなら、そのほうがずっと良いEnumは重いEnumは実態は数値型で生で扱う場合は超軽量ですがそれ以外は重めの処理が入りがちなので注意特にUnityではDictionaryのKeyに使うと都度ボクシングが発生……
Chapter2: JIT Hack
C# ILC++JITASM
ILは大事だが全てではない最初に意識すべきことは、C#はコンパイルされると、どのようなILに変化するかしかし速度的な真の終着点は、どのようなASMで実行されるかCLRの場合はJITコンパイラ、Unityの場合はIL2CPPの結果が大事ほとんどの場合は素直な結果になりますが、時々最適化が走ってILとは異なる結果になる場合もある(EqualityComparer.Defaultのdevirtualizationなどもそう)
インライン化はかなり効くのでうまく使いたい
Chapter3: IL Hack
C#は油断するとすぐに「何か」を生成するC#の便利機能のほとんどが暗黙的な(クラス)生成で成り立っているC#erはGeneration 0のGCは無料だとマントラを唱えていたしかしそれは幻想であり、現実無料ではない更に言えば現状のUnityは世代別GCではないのでより高コスト高速化の基本原則はアロケーションを最小限にすることよし、便利機能は避けようしかし便利機能と思っていなくても分かりにくい罠も存在する
メソッドの直接渡しは暗黙的デリゲート生成public class Foo{public void Bar(){// これはThreadPool.QueueUserWorkItem(RunInThreadPool);// これに等しいThreadPool.QueueUserWorkItem(new WaitCallback(RunInThreadPool));}void RunInThreadPool(object _){Console.WriteLine("foo");}}
可能ならフィールドにキャッシュで回避するpublic class Foo{// もしstaticだったり、インスタンスメソッドでも何度も使うようなものなら// フィールドにキャッシュしてあげるのが良い(ラムダ式の非クロージャの場合はそれを自動で行ってくれる)static readonly WaitCallback CallBack = RunInThreadPool;public void Bar(){ThreadPool.QueueUserWorkItem(CallBack);}static void RunInThreadPool(object _){Console.WriteLine("foo");}}
Action<object>の使い方public int X;public void Bar(){// 「インスタンス変数」などを使いたい場合staticなキャッシュは使えない// しかし勿論これではデリゲートを生成してしまっているThreadPool.QueueUserWorkItem(_ => Nanikasuru());}void Nanikasuru(){Console.WriteLine("Nanika Suru:" + X);}
static readonly WaitCallback CallBack = RunInThreadPool;public int X;public void Bar(){// Action<object>のstateはそのためにある、thisを入れるのが頻出パターン。// これはキャッシュされたデリゲートを使うためゼロアロケーションThreadPool.QueueUserWorkItem(CallBack, this);}static void RunInThreadPool(object state){// stateからthisを引っ張ることでインスタンスメソッドを呼び出せるvar self = (Foo)state;self.Nanikasuru();}void Nanikasuru(){Console.WriteLine("Nanika Suru:" + X);}
ラムダ式のキャプチャstatic void Run(List<int> list, string format){// ラムダ式のキャプチャ(外側の変数を中で使うこと)は暗黙的なクラス生成が入る// 以下のようなコードが生成されるので、クラスとデリゲートの二つがアロケート対象。// var capture = new { format };// new Action<int>(capture.Run);list.ForEach(x =>{Console.WriteLine(string.Format(format, x));});}
ラムダ式のキャプチャstatic void Run(List<int> list, string format){// ラムダ式のキャプチャ(外側の変数を中で使うこと)は暗黙的なクラス生成が入る// 以下のようなコードが生成されるので、クラスとデリゲートの二つがアロケート対象。// var capture = new { format };// new Action<int>(capture.Run);list.ForEach(x =>{Console.WriteLine(string.Format(format, x));});}
static void Run(List<int> list, string format, bool cond){// does not use lambda, but...if (cond){Console.WriteLine("Do Nothing");return;}// use capture pathlist.ForEach(x =>{Console.WriteLine(string.Format(format, x));});}
static void Run(List<int> list, string format, bool cond){// does not use lambda, but...if (cond){Console.WriteLine("Do Nothing");return;}// use capture pathlist.ForEach(x =>{Console.WriteLine(string.Format(format, x));});}
static void Run(List<int> list, string format, bool cond){if (cond){Console.WriteLine("Do Nothing");return;}// キャプチャが存在するメソッドを分けることで回避RunCore(list, format);}static void RunCore(List<int> list, string format){list.ForEach(x =>{Console.WriteLine(string.Format(format, x));});}
文字列の連結はString.Concatに化けるループなど複数回連結が発生するならStringBuilder全て+で繋ぎきれるなら+で繋げてしまうのが良いstatic void Foo(string a, string b, string c, string d){// 以下の形に変換される// var z = string.Concat(a, b, c, d);var z = a + b + c + d;}
static void Foo(string a, int b, string c){var z = a + b + c;}
static void Foo(string a, int b, string c){var z = a + b + c;}
static void Foo(string a, int b, string c){var z = a + b.ToString() + c;}
Chapter4: Binary Hack
Chapter5: async/await Hack
Chapter6:MetaProgramming Hack
Conclusion
C#の言語的なポテンシャルは高いフレームワークやライブラリも揃いつつあり、確かなパフォーマンスを示せているCPU拡張命令を利用した高速化への対応もUnityはBurst Compiler.NET CoreではSystem.Runtime.Intrinsicsなどで対応しつつあるC#の言語的なポテンシャルは高いLinuxでの安定動作も含めて、いよいよ道具が揃いつつあり真のC#元年の幕開けといっても過言ではない
OSSライブラリの開発と公開C#を最前線で戦える言語にしていくため武器を磨く最高のパフォーマンスで基盤を固め、余力を作り出す現実世界で実証する技術とプロダクトは両輪、何事も実証とともにあるべきC#のへの投資が優れた結果を生み出せることを証明していく緩やかな連合の形成C#には情報がない、ではなく軸にして公開して協力していく向かうべき視線は世界!と、堂々と行きましょう

Recommended

PDF
【Unite Tokyo 2019】Understanding C# Struct All Things
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PDF
今日からできる!簡単 .NET 高速化 Tips
PDF
Unity開発で使える設計の話+Zenjectの紹介
PPTX
イベント駆動プログラミングとI/O多重化
PPTX
C# 8.0 非同期ストリーム
PDF
できる!並列・並行プログラミング
PDF
ドメイン駆動設計 本格入門
PDF
Riderはいいぞ!
PDF
こわくない Git
PDF
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
PPTX
世界一わかりやすいClean Architecture
PDF
GoによるWebアプリ開発のキホン
PDF
Twitterのsnowflakeについて
PPTX
C#で速度を極めるいろは
PDF
世界でいちばんわかりやすいドメイン駆動設計
PPTX
最速C# 7.x
PDF
UniTask入門
PDF
【Unity】 Behavior TreeでAIを作る
PDF
Unityでオンラインゲーム作った話
PPTX
BuildKitによる高速でセキュアなイメージビルド
PDF
WebSocket / WebRTCの技術紹介
PDF
テスト文字列に「うんこ」と入れるな
PDF
MagicOnion入門
PPT
Glibc malloc internal
PDF
20分くらいでわかった気分になれるC++20コルーチン
 
PPTX
DockerコンテナでGitを使う
PDF
Pythonによる黒魔術入門
PDF
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
PPTX
Deep Dive C# 6.0

More Related Content

PDF
【Unite Tokyo 2019】Understanding C# Struct All Things
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PDF
今日からできる!簡単 .NET 高速化 Tips
PDF
Unity開発で使える設計の話+Zenjectの紹介
PPTX
イベント駆動プログラミングとI/O多重化
PPTX
C# 8.0 非同期ストリーム
PDF
できる!並列・並行プログラミング
PDF
ドメイン駆動設計 本格入門
【Unite Tokyo 2019】Understanding C# Struct All Things
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
今日からできる!簡単 .NET 高速化 Tips
Unity開発で使える設計の話+Zenjectの紹介
イベント駆動プログラミングとI/O多重化
C# 8.0 非同期ストリーム
できる!並列・並行プログラミング
ドメイン駆動設計 本格入門

What's hot

PDF
Riderはいいぞ!
PDF
こわくない Git
PDF
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
PPTX
世界一わかりやすいClean Architecture
PDF
GoによるWebアプリ開発のキホン
PDF
Twitterのsnowflakeについて
PPTX
C#で速度を極めるいろは
PDF
世界でいちばんわかりやすいドメイン駆動設計
PPTX
最速C# 7.x
PDF
UniTask入門
PDF
【Unity】 Behavior TreeでAIを作る
PDF
Unityでオンラインゲーム作った話
PPTX
BuildKitによる高速でセキュアなイメージビルド
PDF
WebSocket / WebRTCの技術紹介
PDF
テスト文字列に「うんこ」と入れるな
PDF
MagicOnion入門
PPT
Glibc malloc internal
PDF
20分くらいでわかった気分になれるC++20コルーチン
 
PPTX
DockerコンテナでGitを使う
PDF
Pythonによる黒魔術入門
Riderはいいぞ!
こわくない Git
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
世界一わかりやすいClean Architecture
GoによるWebアプリ開発のキホン
Twitterのsnowflakeについて
C#で速度を極めるいろは
世界でいちばんわかりやすいドメイン駆動設計
最速C# 7.x
UniTask入門
【Unity】 Behavior TreeでAIを作る
Unityでオンラインゲーム作った話
BuildKitによる高速でセキュアなイメージビルド
WebSocket / WebRTCの技術紹介
テスト文字列に「うんこ」と入れるな
MagicOnion入門
Glibc malloc internal
20分くらいでわかった気分になれるC++20コルーチン
 
DockerコンテナでGitを使う
Pythonによる黒魔術入門

Similar to CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する

PDF
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
PPTX
Deep Dive C# 6.0
PDF
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
PPTX
C#6.0の新機能紹介
PDF
UniRx - Reactive Extensions for Unity
PPTX
C#/.NETがやっていること 第二版
PPTX
C# 7.2 with .NET Core 2.1
PDF
Burikaigi 2023「C# Live Coding!」 小島の分
PDF
Async design with Unity3D
PDF
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
PDF
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
PDF
Unityで覚えるC#
PDF
A quick tour of the Cysharp OSS
PPTX
C#の書き方
PPTX
C#の書き方
PDF
.NET最先端技術によるハイパフォーマンスウェブアプリケーション
PDF
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
PDF
C#勉強会 ~ C#9の新機能 ~
PPTX
.NET Compiler Platform
PDF
LINQ in Unity
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
Deep Dive C# 6.0
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
C#6.0の新機能紹介
UniRx - Reactive Extensions for Unity
C#/.NETがやっていること 第二版
C# 7.2 with .NET Core 2.1
Burikaigi 2023「C# Live Coding!」 小島の分
Async design with Unity3D
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
Unityで覚えるC#
A quick tour of the Cysharp OSS
C#の書き方
C#の書き方
.NET最先端技術によるハイパフォーマンスウェブアプリケーション
Metaprogramming Universe in C# - 実例に見るILからRoslynまでの活用例
C#勉強会 ~ C#9の新機能 ~
.NET Compiler Platform
LINQ in Unity

More from Yoshifumi Kawai

PDF
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
PDF
Building the Game Server both API and Realtime via c#
PDF
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
PDF
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
PDF
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
PDF
Implements OpenTelemetry Collector in DotNet
PDF
Deep Dive async/await in Unity with UniTask(EN)
PDF
The Usage and Patterns of MagicOnion
PDF
True Cloud Native Batch Workflow for .NET with MicroBatchFramework
PDF
Memory Management of C# with Unity Native Collections
PDF
Deep Dive async/await in Unity with UniTask(UniRx.Async)
PDF
Binary Reading in C#
PDF
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
PPTX
RuntimeUnitTestToolkit for Unity(English)
PPTX
RuntimeUnitTestToolkit for Unity
PDF
NextGen Server/Client Architecture - gRPC + Unity + C#
PDF
How to make the Fastest C# Serializer, In the case of ZeroFormatter
PDF
Photon Server Deep Dive - View from Implmentation of PhotonWire, Multiplayer ...
PDF
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
PPTX
Clash of Oni Online - VR Multiplay Sword Action
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
Building the Game Server both API and Realtime via c#
ライブラリ作成のすゝめ - 事例から見る個人OSS開発の効能
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
Unity C#と.NET Core(MagicOnion) C# そしてKotlinによるハーモニー
Implements OpenTelemetry Collector in DotNet
Deep Dive async/await in Unity with UniTask(EN)
The Usage and Patterns of MagicOnion
True Cloud Native Batch Workflow for .NET with MicroBatchFramework
Memory Management of C# with Unity Native Collections
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Binary Reading in C#
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
RuntimeUnitTestToolkit for Unity(English)
RuntimeUnitTestToolkit for Unity
NextGen Server/Client Architecture - gRPC + Unity + C#
How to make the Fastest C# Serializer, In the case of ZeroFormatter
Photon Server Deep Dive - View from Implmentation of PhotonWire, Multiplayer ...
Photon Server Deep Dive - PhotonWireの実装から見つめるPhotonServerの基礎と応用
Clash of Oni Online - VR Multiplay Sword Action

CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する


[8]ページ先頭

©2009-2025 Movatter.jp