- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在从 USB 设备收集数据,这些数据必须转到音频输出组件。目前,我传送数据的速度不够快,无法避免输出信号中出现咔哒声。所以每一毫秒都很重要。
目前我正在收集以 65536 字节的字节数组形式传送的数据。前两个字节代表 16 位数据,格式为 little endian。这两个字节必须放在 double 组的第一个元素中。后两个字节必须放在不同 double 组的第一个元素中。然后对 65536 缓冲区中的所有字节重复此操作,以便您最终得到 2 个大小为 16384 的 double[]
数组。
我目前正在使用 BitConverter.ToInt16,如代码所示。运行它大约需要 0.3 毫秒,但必须执行 10 次才能将数据包发送到音频输出。所以开销是 3ms,这足以让一些数据包最终无法按时交付。
代码
byte[] buffer = new byte[65536];
double[] bufferA = new double[16384];
double[] bufferB = new double[16384]
for(int i= 0; i < 65536; i +=4)
{
bufferA[i/4] = BitConverter.ToInt16(buffer, i);
bufferB[i/4] = BitConverter.ToInt16(buffer, i+2);
}
我该如何改进?是否可以使用不安全代码复制值?我没有这方面的经验。谢谢
最佳答案
使用 Pointers 和 unsafe
,这使我的发布速度提高了三倍。可能还有其他微优化,但我会将这些细节留给大众
我原来的算法有一个错误,可以改进
修改后的代码
public unsafe (double[], double[]) Test2(byte[] input, int scale)
{
var bufferA = new double[input.Length / 4];
var bufferB = new double[input.Length / 4];
fixed (byte* pSource = input)
fixed (double* pBufferA = bufferA, pBufferB = bufferB)
{
var pLen = pSource + input.Length;
double* pA = pBufferA, pB = pBufferB;
for (var pS = pSource; pS < pLen; pS += 4, pA++, pB++)
{
*pA = *(short*)pS;
*pB = *(short*)(pS + 2);
}
}
return (bufferA, bufferB);
}
每个测试运行 1000 次,在每次运行前收集垃圾,并缩放到不同的数组长度。所有结果都根据原始 OP 版本进行检查
测试环境
----------------------------------------------------------------------------
Mode : Release (64Bit)
Test Framework : .NET Framework 4.7.1 (CLR 4.0.30319.42000)
----------------------------------------------------------------------------
Operating System : Microsoft Windows 10 Pro
Version : 10.0.17134
----------------------------------------------------------------------------
CPU Name : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
Description : Intel64 Family 6 Model 58 Stepping 9
Cores (Threads) : 4 (8) : Architecture : x64
Clock Speed : 3901 MHz : Bus Speed : 100 MHz
L2Cache : 1 MB : L3Cache : 8 MB
----------------------------------------------------------------------------
结果
--- Random Set of byte ------------------------------------------------------
| Value | Average | Fastest | Cycles | Garbage | Test | Gain |
--- Scale 16,384 -------------------------------------------- Time 13.727 ---
| Unsafe | 19.487 µs | 14.029 µs | 71.479 K | 0.000 B | Pass | 59.02 % |
| Original | 47.556 µs | 34.781 µs | 169.580 K | 0.000 B | Base | 0.00 % |
--- Scale 32,768 -------------------------------------------- Time 14.809 ---
| Unsafe | 40.398 µs | 31.274 µs | 145.024 K | 0.000 B | Pass | 56.62 % |
| Original | 93.127 µs | 79.501 µs | 329.320 K | 0.000 B | Base | 0.00 % |
--- Scale 65,536 -------------------------------------------- Time 18.984 ---
| Unsafe | 68.318 µs | 43.550 µs | 245.083 K | 0.000 B | Pass | 68.34 % |
| Original | 215.758 µs | 160.171 µs | 758.955 K | 0.000 B | Base | 0.00 % |
--- Scale 131,072 ------------------------------------------- Time 22.620 ---
| Unsafe | 120.764 µs | 79.208 µs | 428.626 K | 0.000 B | Pass | 71.24 % |
| Original | 419.889 µs | 322.388 µs | 1.461 M | 0.000 B | Base | 0.00 % |
-----------------------------------------------------------------------------
关于c# - 提高 Bitconverter.ToInt16 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52921841/
我需要为 JavaScript 制作简单的 C# BitConverter。我做了一个简单的BitConverter class BitConverter{ constructor(){} GetBy
通常情况下,如果你想在字节数组中表示 5,它会像 {0x00,0x00,0x00,0x05} 一样,但 BitConverter 给我反向数组({0x05,0x00,0x00,0x00})为什么会这样
我正致力于在 .net 核心中编写自己的 DNS 服务器。我正处于对响应有效负载进行编码以发回的阶段,架构显示大多数数字都编码为 16 位数字。 C# 的整数是 32 位数字。没什么大不了的,我只是去
我最近一直在研究 BitConverter 的工作原理,并通过阅读其他 SO 问题,我读到,当起始索引可被转换为可以强制转换的类型的大小整除时,它需要一条“捷径”将索引处的字节指针转换为指向要转换为的
我正在使用 BitConverter.ToInt32 将 3 个 byte 值打包成一个 int,如下所示: byte R = 0; byte G = 0; byte B = 0; int i = B
我尝试将 IP 地址转换为长值: byte[] Ip = new byte[4] { 192, 168, 1, 0 }; UInt32 Ret1 = (((UInt32)Ip[0]) << 24) |
我需要获取 UInt16 和 UInt64 中的值作为 Byte[]。目前我正在使用 BitConverter.GetBytes,但这种方法每次都会给我一个新的数组实例。 我想使用一种允许我将这些值“
我需要 C# BitConverter.DoubleToInt64Bits(doubleValue) 的 Swift 实现。我发现网站上的 C# 实现只是 https://referencesourc
我的代码旨在提取 4 字节消息中的两个中间字节,然后附加两个中间字节以形成一个 16 位无符号整数。不幸的是,我在使用 BitConverter.ToUint16 时遇到问题 - 我的代码似乎无法正常
创建起来非常简单。我有一个简单的字节数组,证明它在运行时有数据: 那我就干 var bytedata = BitConverter.ToUInt32(byte_array,0); 它可以编译,但我在运
这是一个方法- using System; class Program { static void Main(string[] args) { // /
我最近遇到一种情况,我需要创建一个通用方法来从字节数组中读取数据类型。 我创建了以下类: public class DataStream { public int Offset { get;
这个问题在这里已经有了答案: How do you convert a byte array to a hexadecimal string, and vice versa? (52 个答案) 关闭
我正在尝试将一些使用 BitConverter 的现有 C# 代码移植到 Java。我发现了各种其他线程,但后来偶然发现了一个 github 类,它似乎可以解决这个问题。但是,ToUInt16 与我的
在我的程序中,我有一个 PacketFactory,它构建准备好通过 NetworkStream 发送的缓冲区。正如您在下面看到的,此方法采用 short 作为参数。此短消息传递给 BitConver
我正在尝试使用 BitConverter.GetBytes 获取不同类型的不同对象的字节数.为此,我想编写一个通用扩展方法,而不是为我想使用的每种类型(短、长、ulong 等)编写单独的扩展方法。 这
我想知道是否存在与 .Net 的 BitConverter.GetBytes() 方法等效的 Objective C。 例如,在C#中,我可以这样写: byte[] lengthPrefix = Bi
我正在尝试读取文件的 PE header 以获取一些信息。对于 .NET 和 C#,我使用 BitConverter 将读取文件后获得的字节数组转换为等效的整数。我希望对 C++ 做同样的事情,但不确
BitConverter.ToString 给出格式为 'XX-XX-XX-XX' 的十六进制数 是否有相反的方法,以便我可以从以这种格式给出的字符串中获取原始字节数组? 最佳答案 没有,但是很容易实
只是想知道是否有人可以解释为什么以下两行代码返回“不同”的结果?是什么导致了相反的值(value)观?这与字节顺序有关吗? int.MaxValue.ToString("X") //Result: 7
我是一名优秀的程序员,十分优秀!