Здравствуйте, Ночной Смотрящий, Вы писали:
НС>·>С т.з. публичного API — обращение к нему безопасно. А как оно там устроено вунутре — детали имплементации. В шарпе ошибки с Unmanaged memory роняют всё непредсказуемо.
НС>Ничего там непредсказуемо при работе с MMF не роняется, не переживай. Точно так же все завернуто в safe обертку.
Да, ты прав. Оно не роняется, а просто безбожно тормозит. По сравнению с java на микробенчмарке
putLong(getLong() + 1) работает в ~20 раз медленнее (2.5ns vs 45ns). Т.к. там каждое обращение к буферу идёт через обёртку
SafeHandle с ref-counter через volatile, тогда как java просто пишет в область памяти напрямую. По-моему, это на корню убивает идею MMF — когда обращение к замапленной области должна быть просто обращением к физ.памяти. Индусы.
| java |
| import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
public class Program
{
public static void main(String []args) throws Exception
{
try(var fc = FileChannel.open(Paths.get("file.data"), StandardOpenOption.READ, StandardOpenOption.WRITE))
{
var buf = fc.map(FileChannel.MapMode.READ_WRITE, 0, 16);
var t = new Thread(() ->
{
long stopWatch = System.nanoTime();
for(long i = 0; i < 10_000_000_000L; ++i)
{
long val = buf.getLong(0);
buf.putLong(0, val + 1);
if(i % 1_000_000_000L == 0)
{
long stopWatchElapsed = System.nanoTime() - stopWatch;
System.out.println(String.format("i=%s, val=%s, ns=%s", i, val, stopWatchElapsed));
stopWatch = System.nanoTime();
}
}
});
t.setDaemon(true);
t.start();
System.out.println("started");
Thread.sleep(15000);
}
System.out.println("closed");
Thread.sleep(1000);
}
}
|
| |
| c# |
| using System;
using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
class Program
{
static void Main(string[] args)
{
using (var mmf = MemoryMappedFile.CreateFromFile(@"file.data", FileMode.Open))
{
// Create a random access view, from the 256th megabyte (the offset)
// to the 768th megabyte (the offset plus length).
using (var accessor = mmf.CreateViewAccessor(0, 16))
{
var t = new Thread(() =>
{
var stopWatch = Stopwatch.StartNew();
for(int i = 0; i < 1_000_000_000; ++i)
{
long val = accessor.ReadInt64(0);
accessor.Write(0, val + 1);
if(i % 100_000_000 == 0)
{
stopWatch.Stop();
Console.WriteLine("i={0}, val={1}, elapsed={2}", i, val, stopWatch.Elapsed);
stopWatch = Stopwatch.StartNew();
}
}
});
t.Start();
System.Threading.Thread.Sleep(15000);
}
}
System.Threading.Thread.Sleep(1000);
}
}
|
| |