在过程进行过程中,如何测量Files.copy方法的性能/速度? [英] How to measure performance/speed of Files.copy method while the process is on-going?

查看:120
本文介绍了在过程进行过程中,如何测量Files.copy方法的性能/速度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个通用的抽象方法,该方法获取输入流(可以来自网络套接字,也可以来自本地存储中的文件),并将数据保存在磁盘上.

I have a general abstract method which gets an input stream (can be from a network socket, or from a file on the local storage) and saves the data on the disk.

下面是该函数的一小段:

Below a small snippet of the function:

fun saveToFile(data: InputStream, fileDestination: File) {

            val bytesWritten = Files.copy(data, fileDestination.toPath(), StandardCopyOption.REPLACE_EXISTING)
            println("$bytesWritten bytes were saved at ${fileDestination.absolutePath}")

}

在处理/方法进行过程中,是否可以测量将数据保存在磁盘上的速度/速率?例如,是否有可能调用返回速率/速度或更新保存该数据的对象的函数?

Is it possible to measure the speed/rate that the data are being saved on the disk while the process/method is on-going? For example, is there any possibility of invoking a function which returns the rate/speed or updates an object which holds that data?

如果我自己使用InputStream/OutputStream来实现,那么我可能会遇到以下类似情况:

If I was doing the implementation by myself with InputStream/OutputStream, I could have for example something like below:

fun saveData(data: InputStream, fileDestination: File, measureSpeed : (Statistics) -> Unit = { }) {

        val outputStream = fileDestination.outputStream()
        val maxBufferSize = 1024
        val totalAmountData = data.available()
        var totalBytesWritten = 0
        var bytesWriteNextIteration: Int // amount of bytes that will be sent in only one write call
        val statistics = Statistics(amountSent = 0, lastWriteBytes = 0, lastWriteTime = 1)
        while (totalBytesWritten < totalAmountData) {
            bytesWriteNextIteration = totalAmountData - totalBytesWritten
            if (bytesWriteNextIteration > maxBufferSize) {
                bytesWriteNextIteration = maxBufferSize
            }
            val bytes = ByteArray(bytesWriteNextIteration)

            val nano = measureNanoTime {
                outputStream.write(bytes)
            }
            statistics.amountSent = totalBytesWritten.toLong()
            statistics.lastWriteBytes = bytesWriteNextIteration.toLong()
            statistics.lastWriteTime = nano
            measureSpeed(statistics)
            totalBytesWritten += bytesWriteNextIteration
        }

        outputStream.flush()
        outputStream.close()
    }

    data class Statistics(var amountSent: Long, var lastWriteBytes: Long, var lastWriteTime: Long)

并使用measureSpeed方法来计算复印/传输速率.

and with measureSpeed method to calculate the copy/transfer rate.

推荐答案

由于我没有找到任何内置的内容,因此执行要求的最简单方法是重载"所需的Files.copy方法并调用该方法代替功能.

Since I didn't find anything in-built, the easiest way to do what's being asked is to "overload" the desired Files.copy method and call that function instead.

重载方法可能类似于以下内容:

The overloading method could be similar to the below:

private val BUFFER_SIZE = 8192

@Throws(IOException::class)
private fun copy(source: InputStream, sink: OutputStream, networkStatistics: NetworkStatistics, measureSpeed : (NetworkStatistics) -> Unit = { }): Long {
    var nread = 0L
    val buf = ByteArray(BUFFER_SIZE)
    var n: Int
    n = source.read(buf)
    while (n > 0) {
        val nano = measureNanoTime {
            sink.write(buf, 0, n)
            nread += n.toLong()
            n = source.read(buf)
        }
        networkStatistics.amountSent = nread
        networkStatistics.lastPacketBytes = n.toLong()
        networkStatistics.lastPacketTime = nano
        measureSpeed(networkStatistics)
    }
    return nread
}

@Throws(IOException::class)
fun copy(`in`: InputStream, target: Path, networkStatistics: NetworkStatistics, measureSpeed : (NetworkStatistics) -> Unit = { }, vararg options: CopyOption ): Long {
    // ensure not null before opening file
    Objects.requireNonNull(`in`)

    // check for REPLACE_EXISTING
    var replaceExisting = false
    for (opt in options) {
        if (opt === StandardCopyOption.REPLACE_EXISTING) {
            replaceExisting = true
        } else {
            if (opt == null) {
                throw NullPointerException("options contains 'null'")
            } else {
                throw UnsupportedOperationException(opt.toString() + " not supported")
            }
        }
    }

    // attempt to delete an existing file
    var se: SecurityException? = null
    if (replaceExisting) {
        try {
            Files.deleteIfExists(target)
        } catch (x: SecurityException) {
            se = x
        }

    }

    // attempt to create target file. If it fails with
    // FileAlreadyExistsException then it may be because the security
    // manager prevented us from deleting the file, in which case we just
    // throw the SecurityException.
    val ostream: OutputStream
    try {
        ostream = Files.newOutputStream(target, StandardOpenOption.CREATE_NEW,
                StandardOpenOption.WRITE)
    } catch (x: FileAlreadyExistsException) {
        if (se != null)
            throw se
        // someone else won the race and created the file
        throw x
    }

    // do the copy
    ostream.use { out -> return copy(`in`, out, networkStatistics, measureSpeed = { networkStatistics -> measureSpeed(networkStatistics) }) }
}

,它将被称为:

val statistics = NetworkStatistics(responseShouldBe, 0, 0, 1)
copy(inputStream, file.toPath(), statistics, { it: NetworkStatistics -> measureSpeed(it) }, StandardCopyOption.REPLACE_EXISTING)

private fun measureSpeed(stats: NetworkStatistics) {
    val a = stats.lastPacketBytes
    val b = stats.lastPacketTime
    val miliseconds = b.toDouble() / 1000
    val seconds = miliseconds / 1000
    println("$a per ($seconds seconds) or ($miliseconds milisecs) or ($b nanosecs) -- ${(a.toDouble()/(1024*1024))/seconds} MB/seconds")
}

这篇关于在过程进行过程中,如何测量Files.copy方法的性能/速度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆