Иконка ресурса

Скриншоты 2019-02-25

Нет прав для скачивания

CumingSoon

Местный стендапер
1,634
12
269
Ничем. Там пиксели сырыми хранятся, что позволяет мне не создавать дополнительный буфер, не сжимать его. Вместо этого я сразу пишу в файл
 
1,111
47
420
Не, выкидывай, так или иначе наиболее долгий этап это запись на диск. Имеется смысл выносить это в отдельный поток, а если пихнешь в отдельный поток, то и смысла от bmp и mapped буферов нема. Только зря память игроков жрешь.
 

tox1cozZ

aka Agravaine
8,455
598
2,892
То бишь ты сделал скриншот, в чате появилась ссылка на открытие файла, ты клацнул, открылся скриншот, ты глянул и закрыл. Но на диске картиночка не будет сохранена?
 

CumingSoon

Местный стендапер
1,634
12
269
Файл есть, а гарантий, что он уже на ЖД, - нет. Зависит от ос
 
1,111
47
420
Не знал о такой фиче, но прикольно.
Я решил проверить на сколько это годная штука, и попытался записать массив из 1080*1920*3 байт(full hd) 3 разными способами: через map, через обычный OutputStream и через тот же OutputStream только в отдельном потоке. Вот код:
Kotlin:
import java.nio.channels.FileChannel
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
import java.time.Instant
import java.time.temporal.ChronoUnit
import kotlin.concurrent.thread

fun main(args: Array<String>) {
    profile("Mapping creation") {
        val out = Paths.get("lolkek-3").toAbsolutePath()
        val channel =
            FileChannel.open(out, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE)
        val mapped = channel.map(FileChannel.MapMode.READ_WRITE, 0, 3 * 1920 * 1080)
        mapped.put(ByteArray(3 * 1920 * 1080))
        channel.close()

    }
    profile("Direct writing") {
        val out = Paths.get("lolkek-1").toAbsolutePath()
        val channel = Files.newOutputStream(out)
        channel.write(ByteArray(3 * 1920 * 1080))
        channel.flush()

    }
    profile("Async writing") {
        thread(start = true) {
            val out = Paths.get("lolkek-2").toAbsolutePath()
            val channel = Files.newOutputStream(out)
            channel.write(ByteArray(3 * 1920 * 1080))
            channel.flush()
        }
    }
}

private inline fun profile(action: String, block: () -> Unit) {
    val start = Instant.now()
    block()
    val end = Instant.now()
    val delta = ChronoUnit.MILLIS.between(start, end)
    println("$action took ${delta}ms")
}
Вариант c маппингом занимает от 9 до 18 миллисекунд
Вариант с лобовым output стримом от 5 до 15 миллисекунд
Вариант с отдельным потоком от 0 до 3 миллисекунд

Что меня больше всего удивило, так это то, что вариант с маппингом чаще всего оказывался самым медленным.

Перед каждой итерацией я удалял файлы с диска и пару раз передвигал их(да это влияло на производительность).

В реальных же проектах принято все же обжимать картинки хотя бы до png и в таком случае они весят не больше 250кб. И тогда совсем теряется смысл от memmory-mapped файлов. Я вижу смысл использовать такие файлы только в случае когда нужно изменять и читать файл не единожды а многократно. В тех же торрентах например.

P.S. Я знаю про JMH но мне кажется, что результат будет примерно тот же
 

CumingSoon

Местный стендапер
1,634
12
269
Ок, я понял тебя. Вполне возможно, что использование ммап для таких целей - оверфича
Но энивей это не уступает стандартным скриншотом, что меня радует. Да и код получается коротким и простым
Но спасибо за тесты. Я хоть буду знать, что и как работает
 
Сверху