Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

.NET Core 3.0時代のメモリ管理

470 views

Published on

.NET Conf 2019 meetup in AICHI
IMemoryOwner<T>で所有権を説明しようとした

Published in: Technology
  • Be the first to comment

.NET Core 3.0時代のメモリ管理

  1. 1. No CCとあるページを除く
  2. 2. • • Not CC
  3. 3. • • • • • •
  4. 4. • • • • • • •
  5. 5. ⽚付ける物を決める ⼀旦スレッドを停⽌ 停⽌中でないとできない作業を実⾏ スレッド再開 数ms〜数百ms停⽌ ⼯夫はあるが、数ms〜数百ms程度の停⽌時間 Not CC
  6. 6. • • •
  7. 7. • • • • • • C : x y z a b c . t x tstring Span<char>
  8. 8. • • • •
  9. 9. string s = "AA0001"; int.Parse(s.Substring(2, 4)); int.Parse(s.AsSpan().Slice(2, 4)); A A 0 0 0 1 0 0 0 0 1 0 ヒープ確保不要! コピー不要 A A 0 0 0 1 0 Span<char> 現在従来 int.Parseを始めとして、様々なメソッドにSpan<T> を受け取る オーバーロードが追加されている ヒープ確保、コピー
  10. 10. ⻘がマネージヒープ ヒープ確保とGCによる解放を 繰り返すのでジグザグする 新しいヒープを全く確保しない!
  11. 11. • • • •
  12. 12. • • // 過去 unsafe { byte *x = stackalloc byte[100]; } // C# 7.2 Span<byte> x = stackalloc byte[100];
  13. 13. • • • •
  14. 14. • • • • • スタック確保 スタック開放 (レジスタを戻す)
  15. 15. • • static void Test(int size) { Span<byte> buff = size < 1024 ? stackalloc byte[1024] : new byte[1024]; // Do Something } for (int i = 0; i < 10000; i++) { Span<byte> buff = stackalloc byte[1000]; // Do Something }
  16. 16. • • • •
  17. 17. • • • • Memory<T> Span<T> Spanプロパティ
  18. 18. • • •
  19. 19. • • • • •
  20. 20. • • • • • • •
  21. 21. • • • static void Main() { Memory<char> memory = new char[64]; Write(10, memory); Print(memory); } static void Write(int value, Memory<char> buf) { var v = value.ToString(); v.AsSpan().CopyTo(buf.Slice(0,v.Length).Span); } static void Print(Memory<char> buf) => Console.WriteLine(buf);
  22. 22. • static void Main() { using IMemoryOwner<char> owner = MemoryPool<char>.Shared.Rent(); var mem = owner.Memory; Write(10, mem); Print(mem); } static void Write(int value, Memory<char> buf) { var v = value.ToString(); v.AsSpan().CopyTo(buf.Slice(0,v.Length).Span); } static void Print(Memory<char> buf) => Console.WriteLine(buf);
  23. 23. • • • public static string Concat(ReadOnlySpan<char> str0, ReadOnlySpan<char> str1)
  24. 24. • • // だめな例 static void Log(ReadOnlyMemory<char> message) { Task.Run(() => { var sw = File.AppendText(@"log.txt"); sw.WriteLine(message); }); } // 良い例 static void Log(ReadOnlyMemory<char> message) { string defensiveCopy = message.ToString(); Task.Run(() => { var sw = File.AppendText(@“log.txt"); sw.WriteLine(defensiveCopy); sw.Flush(); }); }
  25. 25. • • • // 良い例 static Task Log(ReadOnlyMemory<char> message) { return Task.Run(() => { StreamWriter sw = File.AppendText(@“log.txt"); sw.WriteLine(message); sw.Flush(); }); }
  26. 26. • class Person { public Person(Memory<char> value){ /* Something */ } public Memory<char> FirstName { get; set; } public SetFirstName(Memory<char> value); public Memory<char> FirstName; }
  27. 27. • • • • • 最後に所有権を持った 場所がDispose IMemoryOwner<T>で 所有権の受け渡し
  28. 28. • •
  29. 29. • • • • • • •
  30. 30. • • // BAD public unsafe void Test<T>(T arg) where T : struct { T* ptr = &arg; } // GOOD public unsafe void Test2<T>(T arg) where T : unmanaged { T* ptr = &arg; }
  31. 31. • • public static FileDescriptor[] FromFileGroupDescriptor(ReadOnlySpan<byte> s) { var len = MemoryMarshal.Read<uint>(s); var fs = MemoryMarshal.Cast<byte, FILEDESCRIPTOR>(s.Slice(sizeof(uint))); var list = new FileDescriptor[len]; for (int i = 0; i < len; i++) { list[i] = new FileDescriptor(in fs[i]); } return list; }
  32. 32. • • • public static ref T AsRef<T> (ref T source); public static T Subtract<T> (ref T source, int elementOffset);
  33. 33. • • • • •
  34. 34. • • • •
  35. 35. • • •

×