Why C++ ? 王者归来

本文探讨了C++在软件开发中的重要地位,特别是在性能方面。文章通过Herb Sutter的演讲内容,阐述了C++在不同历史阶段的角色变化,强调了性能优化对于现代计算的重要性,并解释了为何C++在当今的技术环境中仍然具有不可替代的价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文/陈皓

          因为又有人邀请我去 Quora 的 C2C 站去回答问题去了,这回是关于 @laiyonghao 的这篇有点争议的博文《2012 不宜进入的三个技术点》ActionScript,Thread 和 C++, C++ 争议的争议最大。(要我说,.NET 比 C++ 更需要慎重进入,呵)。我就在这里回复一下这个问题吧。

  正好我前段时间看到一个视频,这个演讲视频还比较著名,这个演讲者是 Exceptional C++ C++ Coding Standards 的作者,还是 ISO C++ 委员会的 Chair,C++/CLI 首席架构师,还是 Microsoft 的软件架构师,他叫 Herb Sutter,他的这个演讲视频是 C++ and Beyond 2011上的一次公开演讲,题目是——Why C++? (如果你觉得那里的视频比较慢,你可以看优酷上的视频)(英文听力好的同学可以看一下,因为都没有中文字幕)

  我觉得这篇文章就足够可以说明很多问题了,所以,我把 Herb 的演讲幻灯片截了几页放到这里,并做上一些注释,算是一个演讲内容摘要吧。

  1) 为什么C++?因为 Performance per $,也就是说 performance 就是钱,这个分成三个方面,

  • 电源,芯片的耗电量,移动设备的耗电量,家用电脑的耗电量都和钱有关系。
  • 资源,家用电脑和移动设备上的处理器资源有限,因为要让一般消费者买的起。
  • 体验,在更小的设备上会有更好的体验,有更好的体验就可以挣更多的钱。

  2)C++的进化分成三个时代:

  • 1979 – 1989:研究C的对象能力。主要是为 C++ 做准备
  • 1989 – 1999:C++成了主流。
  • 1999 – 2009:Coffee-based 语言(Java, .NET)出现了,极大的提高了开发生产力。

  对于第三个时代,Herb 说了很多,他说这个并没有什么错,因为这个时候我们非常关注开发的生产力,这个非常重要,这就是为什么 C++ 一下就失去优势的地方。但是是否这些 Coffee-Based 的语言可以做任重要的事呢?不行,很多时候,这是一个 Trade-Off 的事,也就是生产力不是免费的是需要你用别的东西去交换的。

  3)第四个时期。

  Herb 认为,2009-2019是第四个时期,因为我们又喜欢 Native Code 了,C++从被驱逐后又被请回来了。因为网站的性能越来越是个问题,移动端的设备非常流行。但主要是因为 Performance 就是钱,因为前面的三个因素,性能影响的是 dollar,不尊重性能的公司都会发现花钱的速度太快了。(比如去年大家热炒的京东促销和 12306.cn 的问题,12306给整个社会造成了巨大的金钱浪费)

  Herb 把这个时期比做 The Return of the King。(指环王的第三部:王者归来)

  这就好像我在“软件开发的三重门”里说的,开垦时代需要的是快和生产力,而开垦完后就得保证其稳定性。

  4)Herb 还给了一张幻灯片问,“The World is built on ….”,后面例出了多个语言。然后 Herb 说,世界是由C和 C++ 构成的。

  5)Herb 给了一张表格,这张表可相当形像。如果把我们的对编程语言的需求总结为四个:效率,灵活,抽象,生产率。那么,C语言玩的是前两个,而 C++ 玩的是前三个,Java 和 C# 玩的是后两个(抽象和生产率)

  任保一种设计都不可能让你什么都要的,这就是 Trade-Off——什么事都需要交换的。

  6)Herb 举了一个微软内的例子,用C++ 和 ATL 来开发 IE 工具条的报告,因为用 .NET 或是脚本有重大的 limitation,也就是性能问题。

  7)接下来,我们来看看移动设备。

  下图中,第一个是 iOS,第二个是 Android,第三个是 Windows Phone。Herd 说了几个事:

  a)比 Web APP,人们更喜欢 Native 的 APP。

  b)iOS 也好,Android 也好,Windows Phone 也好,他们不是在搞操作系统,而是在搞应用,为的是让智能手机更好。

  c)这三个手机在第一版出来时都不支持C++,而第二版出来时都支持 C++ 了。因为他们要兼顾性能和一定程度上的开发效率。Windows Phone 还没有到第二版,让我们拭目以待。(我以前写过一篇调侃 Android 支持 C++ 开发的文章,这也只是一年前的事,说明 C++ 全面回归了)

  8)如果你还是不相信的话,我们可以看看为什么 Apple 和 Google 都在搞 C++ 的编译器,因为他们觉得G++性能不行。所以,基于 LLVM 的编译器正在领导潮流,因为我们关注 Natvie Code 的性能优化。

  9)接下来,Herb 说了一下数据中心,你知道数据中心最花钱的是什么吗?三个事:

  • 57% 花在了硬件上。
  • 18% 花在了配电和降温上。
  • 13% 花在了耗电上。

  88% 的钱花在了硬件和电力上。这可是很大一笔费用啊。(还有人说硬件比软件便宜吗?)我记得我上一个公司的数据中心每年要花的电费就在百万美元以上。

  10)昨天在微博上有个笑话,说是某咨询师要求程序员把代码打印出来走查,程序员问是不是要用彩打?哈哈。我说,这至少不环保嘛。消耗太大了。是的,C++是可以省电的,以至于 C++ 之父都在 YouTube 说 C++ 是可以减轻全球变暖的问题。哇,C++开始真正造福人类了。

  11)我还需要重温一下老大的这句话——

My contribution to the fight against global warming is C++’s efficiency: Just think if Google had to have twice as many server farms! Each uses as much energy as a small town. And it’s not just a factor of two…Efficiency is not just running fast or running bigger programs, it’s also running using less resources.

Bjarne Stroustrup, June 2011

  最后一句说的非常好!效率不仅仅只是跑得快,跑得多,更是可以使用更少的资源

  12)下面让我们再来看一张表,一张把钱投到哪里的表格。

  • 70 年代 80 年代,资源不够,主要是把钱投在性能上。
  • 80 年代到 90 代,主要是 90 年代开始有一半的投次到了抽象和生产率上。
  • 00 年代,完全都在抽象和生产率上。
  • 10年代,80% 的钱都要回头来解决性能问题。这就是C/C++的王者归来。

  13)当然,不是 C++ 不注重开发效率,看看C++0X 的标准引入了多少东西我们就知道了。但是本质上,C++还是致力于性能和抽象的完全平衡

  那么,我们还会觉得 C++ 要被淘汰了,不适合进入了吗?

  后面讲了 C++ 的文艺复兴,你可以在 Google 搜索 “C++ Renaissance”看看。另外,该视频的讲议可以在这里下载

转载于:https://www.cnblogs.com/anndaming/archive/2012/03/10/2388824.html

<think>我们之前已经详细讨论了JavaCV中Frame压缩图片的三种方法,但用户当前的问题似乎有些模糊。根据引用内容,用户可能是在追问之前回答的细节,或者对某些部分存在疑问。由于引用内容涉及多个领域(PCL点云库、Spring异步、OpenCV视频去水印、FFmpeg视频转图片等),但都与JavaCV图片压缩没有直接关联,因此我们需要回归到用户最初的问题。用户最初的问题是:“使用JavaCV中的Frame压缩图片有几种方法”,我们已经给出了三种方法的详细实现和对比。现在用户再次提问,可能是想了解:1.为什么使用这些方法?2.具体实现中的细节问题?3.或者对之前回答的补充?考虑到用户引用的内容中出现了OpenCV和FFmpeg(这与方法1和方法2对应),我们可以进一步强化这两种方法的解释。###补充说明:方法1(OpenCV)的核心优势在引用[3]中,OpenCV被用于视频去水印,说明OpenCV在图像处理领域有强大的功能。因此使用方法1进行图片压缩时,可以利用OpenCV丰富的编码参数(如JPEG质量、PNG压缩级别等)进行精细控制。###补充说明:方法2(FFmpeg)的适用场景引用[4]展示了用FFmpeg将视频帧保存为图片,这与方法2的原理一致。当处理连续视频帧时,使用`FFmpegFrameRecorder`可以保持高效的编码性能。###用户可能需要的额外方法:批量压缩引用[2]提到了Spring的异步处理,这启发了我们:对于大批量图片压缩,可以结合异步处理提升效率。例如:```java@ServicepublicclassAsyncImageCompressor{@AsyncpublicvoidcompressBatchAsync(List<Frame>frames,StringoutputDir){//使用OpenCV方法并行压缩frames.parallelStream().forEach(frame->{StringoutputPath=outputDir+"/frame_"+System.currentTimeMillis()+".jpg";compressWithOpenCV(frame,outputPath,85);//质量85%});}}```###针对用户当前问题的完整回答虽然用户的问题表述不够明确,但结合上下文,我们推测用户需要的是对之前三种方法的进一步解释或扩展应用。因此,我们补充以下内容:---###扩展:方法4(批量压缩与异步处理)当需要处理大量帧(如视频截图)时,可结合并行流和异步调用:```javaimportorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;importjava.util.List;@ServicepublicclassBatchImageCompressor{privatefinalOpenCVFrameConverter.ToMatconverter=newOpenCVFrameConverter.ToMat();@AsyncpublicCompletableFuture<Void>compressFramesAsync(List<Frame>frames,StringoutputDir,intquality){frames.parallelStream().forEach(frame->{Matmat=converter.convert(frame);Stringfilename=outputDir+"/frame_"+frame.timestamp+".jpg";int[]params={opencv_imgcodecs.IMWRITE_JPEG_QUALITY,quality};imwrite(filename,mat,params);});returnCompletableFuture.completedFuture(null);}}```**特点:**-使用Spring的`@Async`实现异步调用[^2]-通过`parallelStream()`并行处理帧-避免主线程阻塞,适合Web应用---###总结:四种JavaCVFrame压缩方法|方法|新增特性||--------------------|--------------------------||OpenCV单帧压缩|参数精细,速度快||FFmpeg单帧录制|视频帧处理优化||JavaImageIO|无需额外Native库||**批量异步压缩**|高吞吐量,非阻塞|>**选择指南:**>-单张图片:方法1>方法3>-视频流帧:方法2>-大规模批量:方法4§§相关问题§§1.如何在SpringBoot项目中集成JavaCV的图片压缩功能?2.使用OpenCV压缩图片时如何避免内存泄漏?3.FFmpegFrameRecorder压缩单帧图片时如何设置更高级的编码参数?</think>### JavaCV Frame 图片压缩方法详解 在 JavaCV 中压缩 `Frame` 对象主要有 **3 种核心方法**,每种方法针对不同场景优化。以下是详细解释和实现: --- #### 方法 1:OpenCV 原生压缩(推荐) **原理**:利用 OpenCV 的高性能图像编码器 **优势**:压缩质量精细控制,支持多种格式 ```java import org.bytedeco.javacv.*; import org.bytedeco.opencv.opencv_core.Mat; import static org.bytedeco.opencv.global.opencv_imgcodecs.*; public void compressWithOpenCV(Frame frame, String outputPath, int quality) { // Frame → Mat 转换 try (OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat()) { Mat mat = converter.convert(frame); // 设置压缩参数(JPEG质量0-100) int[] params = {IMWRITE_JPEG_QUALITY, quality}; // 执行压缩保存 imwrite(outputPath, mat, params); } } ``` **关键参数**: - `quality`: 压缩质量 (0=最低, 100=无损) - 支持格式:JPEG/PNG/WEBP/TIFF **适用场景**:需要精确控制压缩质量的静态图像处理[^3] --- #### 方法 2:FFmpeg 帧录制压缩 **原理**:通过视频编码器处理单帧图像 **优势**:支持硬件加速,适合视频流处理 ```java import org.bytedeco.javacv.*; public void compressWithFFmpeg(Frame frame, String outputPath) throws Exception { try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder( outputPath, frame.imageWidth, frame.imageHeight)) { // 关键参数配置 recorder.setFormat("image2"); // 图片格式 recorder.setPixelFormat(AV_PIX_FMT_YUV420P); // 色彩空间 recorder.setVideoCodec(AV_CODEC_ID_MJPEG); // 编码格式 // 单帧录制压缩 recorder.start(); recorder.record(frame); } } ``` **色彩空间说明**: - `YUV420P`:视频压缩常用色彩空间,节省30%带宽 - `RGB24`:保持原始色彩但体积较大 **适用场景**:视频帧抽取压缩(如视频转图片序列)[^4][^5] --- #### 方法 3:Java2D 中转压缩 **原理**:通过 BufferedImage 使用 Java 原生压缩 **优势**:无 Native 依赖,简单易用 ```java import javax.imageio.*; import java.awt.image.*; public void compressWithImageIO(Frame frame, String outputPath, float quality) throws Exception { // Frame → BufferedImage 转换 Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage img = converter.convert(frame); // 高级压缩参数控制 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("JPEG"); try (ImageOutputStream ios = ImageIO.createImageOutputStream(new File(outputPath))) { ImageWriter writer = writers.next(); writer.setOutput(ios); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); // 0.0-1.0 writer.write(null, new IIOImage(img, null, null), param); } } ``` **适用场景**:轻量级应用或无法使用 Native 库的环境 --- ### 性能对比与选型指南 | 方法 | 压缩速度 | 质量控制 | 硬件加速 | 适用场景 | |--------------|----------|----------|----------|------------------------| | OpenCV | ⚡️ 极快 | ✅ 精细 | ✅ 支持 | 高质量静态图像 | | FFmpeg | ⚡️ 快 | ⚠️ 中等 | ✅ 支持 | 视频帧/实时流处理[^4] | | Java ImageIO | ⚠️ 中等 | ⚠️ 基础 | ❌ 不支持 | 简单应用/无 Native 环境 | > **最佳实践建议**: > 1. 优先选择 **OpenCV 方法**(质量/速度均衡) > 2. 处理视频流时使用 **FFmpeg 方法**(硬件加速优势) > 3. 简单场景用 **Java2D 方法**(零依赖) --- ### 常见问题解答 **Q1: 为什么压缩后图像色彩异常?** A: 因色彩空间转换导致: - OpenCV/FFmpeg 默认使用 BGR 色彩空间 - 解决方案:转换时指定色彩空间 ```java // 转换时指定RGB格式 Mat rgbMat = new Mat(); cvtColor(originalMat, rgbMat, COLOR_BGR2RGB); ``` **Q2: 如何实现批量压缩?** A: 结合并行流提升性能: ```java List<Frame> frames = ... // 获取帧序列 frames.parallelStream().forEach(frame -> { compressWithOpenCV(frame, "output_"+System.nanoTime()+".jpg", 85); }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值