ITPub博客

首页 > 大数据 > ELK > 运行方式(可复现命令)

运行方式(可复现命令)

投稿 ELK 作者:ecclw459 时间:2026-01-28 16:25:57 0 删除 编辑

# Java 21 cd /app/bigintbench/java javac BigIntBench.java java -Xms1g -Xmx1g -XX:+UseG1GC -XX:+AlwaysPreTouch BigIntBench --json # .NET 10 cd /app/bigintbench/csharp dotnet build -c Release


{"lang":"java","bits":256,"op":"ADD_MOD","ops":1999872,"nsPerOp":139.589,"checksum":0}
{"lang":"java","bits":256,"op":"MUL_MOD","ops":499712,"nsPerOp":387.031,"checksum":0}
{"lang":"java","bits":256,"op":"MODPOW","ops":7936,"nsPerOp":17764.884,"checksum":0}
{"lang":"java","bits":1024,"op":"ADD_MOD","ops":999424,"nsPerOp":284.672,"checksum":0}
{"lang":"java","bits":1024,"op":"MUL_MOD","ops":119808,"nsPerOp":3094.540,"checksum":0}
{"lang":"java","bits":1024,"op":"MODPOW","ops":1280,"nsPerOp":264577.852,"checksum":0}
{"lang":"java","bits":4096,"op":"ADD_MOD","ops":199680,"nsPerOp":900.735,"checksum":0}
{"lang":"java","bits":4096,"op":"MUL_MOD","ops":19456,"nsPerOp":32062.554,"checksum":0}
{"lang":"java","bits":4096,"op":"MODPOW","ops":256,"nsPerOp":3422756.113,"checksum":0}

.NET 10: results_csharp.jsonl

{"lang":"csharp","bits":256,"op":"ADD_MOD","ops":1999872,"nsPerOp":146.261,"checksum":0}
{"lang":"csharp","bits":256,"op":"MUL_MOD","ops":499712,"nsPerOp":560.246,"checksum":0}
{"lang":"csharp","bits":256,"op":"MODPOW","ops":7936,"nsPerOp":169713.608,"checksum":0}
{"lang":"csharp","bits":1024,"op":"ADD_MOD","ops":999424,"nsPerOp":297.335,"checksum":0}
{"lang":"csharp","bits":1024,"op":"MUL_MOD","ops":119808,"nsPerOp":4792.760,"checksum":0}
{"lang":"csharp","bits":1024,"op":"MODPOW","ops":1280,"nsPerOp":1938407.720,"checksum":0}
{"lang":"csharp","bits":4096,"op":"ADD_MOD","ops":199680,"nsPerOp":1280.760,"checksum":0}
{"lang":"csharp","bits":4096,"op":"MUL_MOD","ops":19456,"nsPerOp":36894.568,"checksum":0}
{"lang":"csharp","bits":4096,"op":"MODPOW","ops":256,"nsPerOp":20617970.004,"checksum":0}


实验二:加入 Java 8 ——看“现状主流”处于什么位置

这一组的关键点是: 同一份 Java 源码用 Java 8 编译,分别在 Java 8 与 Java 21 上运行,尽量避免“编译器产物差异”。

4.1 运行方式

# 编译(Java 8)/path/to/jdk8/bin/javac BigIntBench.java# 运行(Java 8)/path/to/jdk8/bin/java -Xms1g -Xmx1g -XX:+UseG1GC -XX:+AlwaysPreTouch BigIntBench --json# 运行(Java 21)java -Xms1g -Xmx1g -XX:+UseG1GC -XX:+AlwaysPreTouch BigIntBench --json

4.2 实验二原始输出(JSONL)

Java 8: results_java8.jsonl

{"lang":"java","bits":256,"op":"ADD_MOD","ops":1999872,"nsPerOp":207.335,"checksum":0}
{"lang":"java","bits":256,"op":"MUL_MOD","ops":499712,"nsPerOp":468.248,"checksum":0}
{"lang":"java","bits":256,"op":"MODPOW","ops":7936,"nsPerOp":17697.113,"checksum":0}
{"lang":"java","bits":1024,"op":"ADD_MOD","ops":999424,"nsPerOp":390.906,"checksum":0}
{"lang":"java","bits":1024,"op":"MUL_MOD","ops":119808,"nsPerOp":3089.474,"checksum":0}
{"lang":"java","bits":1024,"op":"MODPOW","ops":1280,"nsPerOp":277395.652,"checksum":0}
{"lang":"java","bits":4096,"op":"ADD_MOD","ops":199680,"nsPerOp":990.708,"checksum":0}
{"lang":"java","bits":4096,"op":"MUL_MOD","ops":19456,"nsPerOp":30692.214,"checksum":0}
{"lang":"java","bits":4096,"op":"MODPOW","ops":256,"nsPerOp":3468269.539,"checksum":0}


  1. Java 8 vs Java 21: 毫无疑问,Java 21 在绝大多数情况下都比老迈的 Java 8 要快。不过有趣的是,在  MUL_MOD 的 1024 和 4096 位测试中,Java 8 居然出现了“反超”的现象。这可能是由于 JIT 策略、算法选择的阈值差异,或是单纯的测量误差。虽然这不影响“Java 21更快”的总体结论,但也提醒我们性能测试的复杂性。

总而言之,这次对决让我们清楚地看到,在复杂的大数运算上,.NET 的  BigInteger 确实还有很长的路要走。


One More Thing:当“外援”登场

在寻找 .NET 大数性能优化方案的过程中,我们自然能想到了业界标杆 GMP ——它是 GNU Multi-Precision Arithmetic Library,很多数学软件/密码学实现都会用它做高性能大整数运算。

我碰巧也为它做了一个 .NET 封装: Sdcb.Arithmetic。

但必须提前声明: 让 GMP 作为“外援”加入这场对比,是“不公平”的。原因很简单:

  • 语言优势:GMP 是原生 C/汇编,而 .NET 和 Java 是在虚拟机上运行的托管语言。
  • 内存策略:GMP 鼓励使用  in-place API,可以直接在原地修改数值,大大减少了内存分配和 GC 压力。而 .NET 和 Java 的  BigInteger 则是不可变对象。

所以,这部分的结果更像是一个“彩蛋”,展示的是: 如果你愿意引入原生依赖,并改变编码风格,.NET 的大数性能可以达到怎样的高度。


using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Numerics; using Sdcb.Arithmetic.Gmp; sealed class SplitMix64 {     private ulong _x;     public SplitMix64( ulong seed) => _x = seed;     public ulong NextUInt64()    {         ulong z = (_x += 0x9E3779B97F4A7C15 UL);        z = (z ^ (z >> 30 )) * 0xBF58476D1CE4E5B9 UL;        z = (z ^ (z >> 27 )) * 0x94D049BB133111EB UL;         return z ^ (z >> 31 );    }     public void NextBytes( byte[] dst)    {         int i = 0 ;         while (i < dst.Length)        {             ulong v = NextUInt64();             for ( int k = 0 ; k < 8 && i < dst.Length; k++)                dst[i++] = ( byte )(v >> ( 56 - 8 * k));        }    } } enum Op { ADD_MOD, MUL_MOD, MODPOW } record Result ( string Impl , int Bits , Op Op , long Ops , double NsPerOp , long Checksum )wap.7632.com.cn。 {     public string ToJson() => string .Create(CultureInfo.InvariantCulture,         $"{{\"lang\":\" {Impl}\",\"bits\": {Bits},\"op\":\" {Op}\",\"ops\": {Ops},\"nsPerOp\": {NsPerOp:F3},\"checksum\": {Checksum}}}" ); } static class BenchUtil {     public static void MaskToBitSize( byte[] buf, int bitSize)    {         int topBit = (bitSize - 1 ) % 8 ;         int keepBits = topBit + 1 ;         int firstMask = keepBits == 8 ? 0xFF : (( 1 << keepBits) - 1 );        buf[ 0 ] &= ( byte )firstMask;        buf[ 0 ] |= ( byte )( 1 << topBit);m.psnsd.com,    }     public static string ToHex( byte[] bytes) => Convert.ToHexString(bytes); } static class BigIntegerBench {     public static BigInteger[] Gen( int bitSize, int count, ulong seed)    {         var rng = new SplitMix64(seed);         int byteLen = (bitSize + 7 ) / 8 ;         var arr = new BigInteger[count];  m.xyxdLsm.com,       var buf = new byte [byteLen];         for ( int i = 0 ; i < count; i++)        {            rng.NextBytes(buf);            BenchUtil.MaskToBitSize(buf, bitSize);            arr[i] = new BigInteger(buf, isUnsigned: true , isBigEndian: true );        }         return arr;    }     public static BigInteger GenModulus( int bitSize, ulong seed)    {         var rng = new SplitMix64(seed);         int byteLen = (bitSize + 7 ) / 8 ;         var buf = new byte [byteLen];jtwL.com.cn,        rng.NextBytes(buf);        BenchUtil.MaskToBitSize(buf, bitSize);        buf[^ 1 ] |= 1 ;         return new BigInteger(buf, isUnsigned: true , isBigEndian: true );    }     public static long RunOnce( Op op, BigInteger[] a, BigInteger[] b, BigInteger[] e, BigInteger mod, int outer)    {        BigInteger acc = BigInteger.Zero;         int n = a.Length;         switch (op)        {             case Op.ADD_MOD:                 for ( int o = 0 ; o < outer; o++)                     for ( int i = 0 ; i < n; i++)                        acc ^= (a[i] + b[i]) % mod;                 break ;             case Op.MUL_MOD:m.psnsd.com,                 for ( int o = 0 ; o < outer; o++)                     for ( int i = 0 ; i < n; i++)                        acc ^= (a[i] * b[i]) % mod;                 break ;             case Op.MODPOW:                 for ( int o = 0 ; o < outer; o++)                     for ( int i = 0 ; i < n; i++)                        acc ^= BigInteger.ModPow(a[i], e[i], mod);                 break ;        }         return ( long )(acc & long .MaxValue);    } } static class GmpIntegerBench {     public static GmpInteger[] Gen( int bitSize, int count, ulong seed)    {         var rng = new SplitMix64(seed);         int byteLen = (bitSize + 7 ) / 8 ;         var arr = new GmpInteger[count];  m.7632.com.cn,       var buf = new byte [byteLen];         for ( int i = 0 ; i < count; i++)        {            rng.NextBytes(buf);            BenchUtil.MaskToBitSize(buf, bitSize);            arr[i] = GmpInteger.Parse(BenchUtil.ToHex(buf), 16 );        }         return arr;firstfeed.com.cn,    }     public static GmpInteger GenModulus( int bitSize, ulong seed)    {         var rng = new SplitMix64(seed);         int byteLen = (bitSize + 7 ) / 8 ;         var buf = new byte [byteLen];        rng.NextBytes(buf);        BenchUtil.MaskToBitSize(buf, bitSize);        buf[^ 1 ] |= 1 ;         return GmpInteger.Parse(BenchUtil.ToHex(buf), 16 );    }     public static long RunOnce( Op op, GmpInteger[] a, GmpInteger[] b, GmpInteger[] e, GmpInteger mod, int outer)    {         using var acc = GmpInteger.From( 0 );         using var tmp = GmpInteger.From( 0 );         int n = a.Length;  wap.xmich.cn,       switch (op)        {             case Op.ADD_MOD:                 for ( int o = 0 ; o < outer; o++)                     for ( int i = 0 ; i < n; i++)                    {                        GmpInteger.AddInplace(tmp, a[i], b[i]);                        GmpInteger.ModInplace(tmp, tmp, mod);                        GmpInteger.BitwiseXorInplace(acc, acc, tmp);                    }                 break ;             case Op.MUL_MOD:                 for ( int o = 0 ; o < outer; o++)                     for ( int i = 0 ; i < n; i++)                    {www.siLkcraft.com.cn,                        GmpInteger.MultiplyInplace(tmp, a[i], b[i]);                        GmpInteger.ModInplace(tmp, tmp, mod);                        GmpInteger.BitwiseXorInplace(acc, acc, tmp);                    }                 break ;             case Op.MODPOW:                 for ( int o = 0 ; o < outer; o++)                     for ( int i = 0 ; i < n; i++)                    {                        GmpInteger.PowerModInplace(tmp, a[i], e[i], mod);                        GmpInteger.BitwiseXorInplace(acc, acc, tmp);                    }                 break ;        }         return acc.GetHashCode();    }     public static void DisposeAll( GmpInteger[] xs)    {         foreach ( var x in xs) x.Dispose();    } } static class Runner {     static Result BenchBigInteger( int bits, Op op, BigInteger[] a, BigInteger[] b, BigInteger[] e, BigInteger mod, long targetOps, int warmups, int measures)    {         int n = a.Length;  murnis.cn,       int outer = ( int )Math.Max( 1 , targetOps / n);         long actualOps = ( long )n * outer;         long ck = 0 ;         for ( int i = 0 ; i < warmups; i++) ck ^= BigIntegerBench.RunOnce(op, a, b, e, mod, outer);         long [] timesNs = new long [measures];         for ( int i = 0 ; i < measures; i++)        {             var sw = Stopwatch.StartNew();             long c = BigIntegerBench.RunOnce(op, a, b, e, mod, outer);            sw.Stop();            ck ^= c;            timesNs[i] = ( long )(sw.ElapsedTicks * ( 1 _000_000_000 .0 / Stopwatch.Frequency));        }        Array.Sort(timesNs);         long median = timesNs[timesNs.Length / 2 ];         return new Result( "csharp_bigint" , bits, op, actualOps, ( double )median / actualOps, ck);    }     static Result BenchGmpInteger( int bits, Op op, GmpInteger[] a, GmpInteger[] b, GmpInteger[] e, GmpInteger mod, long targetOps, int warmups, int measures)    {         int n = a.Length;         int outer = ( int )Math.Max( 1 , targetOps / n);         long actualOps = ( long )n * outer; m.ntnet.com.cn,       long ck = 0 ;         for ( int i = 0 ; i < warmups; i++) ck ^= GmpIntegerBench.RunOnce(op, a, b, e, mod, outer);         long [] timesNs = new long [measures];         for ( int i = 0 ; i < measures; i++)        {             var sw = Stopwatch.StartNew();             long c = GmpIntegerBench.RunOnce(op, a, b, e, mod, outer);            sw.Stop();            ck ^= c;            timesNs[i] = ( long )(sw.ElapsedTicks * ( 1 _000_000_000 .0 / Stopwatch.Frequency));        }        Array.Sort(timesNs);         long median = timesNs[timesNs.Length / 2 ];         return new Result( "csharp_gmp_inplace" , bits, op, actualOps, ( double )median / actualOps, ck);    }     public static int Run( string[] args)    {         bool json = args.Any(a => a == "--json" );         int warmups = 5 ;         int measures = 11 ;         int [] bitSizes = [ 256 , 1024 , 4096 ];    m.njyf.com.cn,     var results = new List<Result>();         foreach ( int bits in bitSizes)bakmk.com,        {             long addOps = bits switch { 256 => 2 _000_000L, 1024 => 1 _000_000L, _ => 200 _000L };             long mulOps = bits switch { 256 => 500 _000L, 1024 => 120 _000L, _ => 20 _000L };             long powOps = bits switch { 256 => 8 _000L, 1024 => 1 _500L, _ => 250L };             // BigInteger data             var modB = BigIntegerBench.GenModulus(bits, 0xA1B2C3D4E5F60708 UL ^ ( uint )bits);             var aB = BigIntegerBench.Gen(bits, 1024 , 0x1111222233334444 UL ^ ( uint )bits);             var bB = BigIntegerBench.Gen(bits, 1024 , 0x9999AAAABBBBCCCC UL ^ ( uint )bits);             var apB = BigIntegerBench.Gen(bits, 256 , 0x13579BDF2468ACE0 UL ^ ( uint )bits);             var epB = BigIntegerBench.Gen(Math.Min(bits, 512 ), 256 , 0x0FEDCBA987654321 UL ^ ( uint )bits);             // GmpInteger data (same seeds/bit sizes)             using var modG = GmpIntegerBench.GenModulus(bits, 0xA1B2C3D4E5F60708 UL ^ ( uint )bits);             var aG = GmpIntegerBench.Gen(bits, 1024 , 0x1111222233334444 UL ^ ( uint )bits);             var bG = GmpIntegerBench.Gen(bits, 1024 , 0x9999AAAABBBBCCCC UL ^ ( uint )bits);             var apG = GmpIntegerBench.Gen(bits, 256 , 0x13579BDF2468ACE0 UL ^ ( uint )bits);             var epG = GmpIntegerBench.Gen(Math.Min(bits, 512 ), 256 , 0x0FEDCBA987654321 UL ^ ( uint )bits);             try            {jsastone.com.cn,                results.Add(BenchBigInteger(bits, Op.ADD_MOD, aB, bB, null !, modB, addOps, warmups, measures));                results.Add(BenchBigInteger(bits, Op.MUL_MOD, aB, bB, null !, modB, mulOps, warmups, measures));m.huome.cn,                results.Add(BenchBigInteger(bits, Op.MODPOW, apB, null !, epB, modB, powOps, warmups, measures));                results.Add(BenchGmpInteger(bits, Op.ADD_MOD, aG, bG, null !, modG, addOps, warmups, measures));m.murnis.cn,                results.Add(BenchGmpInteger(bits, Op.MUL_MOD, aG, bG, null !, modG, mulOps, warmups, measures));                results.Add(BenchGmpInteger(bits, Op.MODPOW, apG, null !, epG, modG, powOps, warmups, measures));wap.qzsxy.com,            }             finally            {                GmpIntegerBench.DisposeAll(aG);                GmpIntegerBench.DisposeAll(bG);                GmpIntegerBench.DisposeAll(apG);                GmpIntegerBench.DisposeAll(epG);            }        }         if (json)        {             foreach ( var r in results) Console.WriteLine(r.ToJson());        }         return 0 ;    } } public static class Program {     public static int Main( string[] args) => Runner.Run(args);

 <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>,wap.czjzz.com,
  <ItemGroup>
    <PackageReference Include="Sdcb.Arithmetic.Gmp" Version="*" />
    <PackageReference Include="Sdcb.Arithmetic.Gmp.runtime.linux-x64" Version="*" />
  </ItemGroup></Project>

7.2 客串实验原始输出(JSONL)

{"lang":"csharp_bigint","bits":256,"op":"ADD_MOD","ops":1999872,"nsPerOp":146.261,"checksum":0}
{"lang":"csharp_bigint","bits":256,"op":"MUL_MOD","ops":499712,"nsPerOp":560.246,"checksum":0}
{"lang":"csharp_bigint","bits":256,"op":"MODPOW","ops":7936,"nsPerOp":169713.608,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":256,"op":"ADD_MOD","ops":1999872,"nsPerOp":76.644,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":256,"op":"MUL_MOD","ops":499712,"nsPerOp":114.690,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":256,"op":"MODPOW","ops":7936,"nsPerOp":13931.914,"checksum":0}
{"lang":"csharp_bigint","bits":1024,"op":"ADD_MOD", wap.moyizhai.com,"ops":999424,"nsPerOp":297.335,"checksum":0}
{"lang":"csharp_bigint","bits":1024,"op":"MUL_MOD","ops":119808,"nsPerOp":4792.760,"checksum":0}
{"lang":"csharp_bigint","bits":1024,"op":"MODPOW","ops":1280,"nsPerOp":1938407.720,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":1024,"op":"ADD_MOD","ops":999424,"nsPerOp":97.260,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":1024,"op":"MUL_MOD","ops":119808,"nsPerOp":562.235,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":1024,"op":"MODPOW","ops":1280,"nsPerOp":218715.147,"checksum":0}
{"lang":"csharp_bigint",,m.qieroom.com,"bits":4096,"op":"ADD_MOD","ops":199680,"nsPerOp":1280.760,"checksum":0}
{"lang":"csharp_bigint","bits":4096,"op":"MUL_MOD","ops":19456,"nsPerOp":36894.568,"checksum":0}
{"lang":"csharp_bigint","bits":4096,"op":"MODPOW","ops":256,"nsPerOp":20617970.004,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":4096,"op":"ADD_MOD","ops":199680,"nsPerOp":179.720,"checksum":0}
{"lang":"csharp_gmp_inplace","bits":4096,"op":"MUL_MOD","ops":19456,"nsPerOp":5431.441,"checksum":0}




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3109275/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102113