什么在Android上表现更好?用Java或c++编写的应用程序

What will perform better on Android? An app written with Java or C++

本文关键字:c++ Java 应用程序 Android 更好 什么      更新时间:2023-10-16

在Qt上使用c++编写的Android设备应用程序比使用Android SDK使用Java编写的应用程序性能更好吗?

似乎所有其他的答案都是关于c++和Java的争论,所以我将尝试分享我在Android中关于Java和Qt编程的经验和知识。

首先,Android SDK是用Java实现的,因此开发者应该默认使用Java。

.

更多的性能和更多的控制

但是在某些情况下需要更高的性能。游戏就是一个例子。图像处理是另一个用例。
在某些情况下,您需要使用c++来更好地控制硬件。(例如使用频率更高的加速度计)

Android使用一个名为Dalvik的特定虚拟机(直到版本5)。任何需要UI的应用都需要Dalvik。所以c++应用程序(游戏和Qt等)需要包含Dalvik。

也没有c++库来直接利用c++中的服务和操作系统特性(如联系人簿)。因此,您需要在使用c++的同时使用Java。为此,您需要在.java文件中编写一些Java代码,并且需要使用JNI来通信c++和Java。JNI是您需要学习的另一个有问题的东西。
因此,使用c++开发Android应用程序比普通Java应用程序要困难得多。
.

我在Android上的Qt体验

我用QtQtQuick编写了一些Android应用程序,没有QtQuick控件。QtQuick对于UI开发来说是很棒的,但你需要做一些事情,比如手动管理加载和卸载UI。这不是问题,因为QtQuick中有一些用于此目的的功能,如Loader
在桌面中实现应用程序的一般部分(非特定于Android部分)是非常高效、快速和有趣的(c++和QtQuick)。
但是在JNI中实现Android特定的部分需要更多的时间和精力。

.

Android上的Qt -利弊

  • APK包很大(大多数情况下开销约为8mb)
  • 需要发布多个APK包(ARM, x86) (Google play让你做得很好,没有最终用户通知)
  • 应用启动时间高于正常应用
  • 需要通过JNI
  • 使用c++和Java结合开发调试困难<<li>更少的文档/gh>
  • 及其快速UI
  • 如果你打算在iOS等其他平台上发布应用,你只需要重新实现特定于操作系统的部分。这样你的时间/成本就会降低。
  • 高性能后端处理和整体应用性能
  • 更好的内存管理
  • 在Android 2.2(例如)直到7.0质量相同!(Android SDK的一些功能只是在更高版本中,因此如果你打算支持较低版本的Android,你就不能使用这些功能。比如AnimationFramework。使用Qt你不会有这个问题)
  • 在早期Android版本和更高版本中使用HW加速UI
  • 源代码保护
  • 视图和模型/控制器的良好分离(有助于专业编码)
  • 简单快速的UI开发简单而漂亮的UI效果(OpenGLES &(也自然集成到UI的其他组件)

.

建议

如果(你不是Qt经验丰富的开发人员)=>使用Java

IF(你只需要一些处理的性能)=>Java + c++ (NDK)

如果(您是Qt经验丰富的开发人员)和((您是Java初学者)或(您计划将您的应用程序移植到其他平台))=>在c++中使用Qt

让我们将其分为两部分:

1) c++的性能会比Java好吗?

是的。当然会。它总是这样做的,只要您不向Java调用太多JNI。这就是为什么人们(包括Google)在性能最重要的地方使用c++。

2) QT是否比使用JNI返回Java或在NDK中使用c++可用的原始调用更好?

假设您以最佳方式编写这两种代码,顺序可能是原始NDK调用> Java调用> QT调用。QT库只是要做和你完全一样的函数调用,它只是在上面放了一个不同的抽象层。这一层会增加开销。大多数时候,开销可能是最小的。如果你是一个有经验的QT程序员,你可能会使用QT更快地编写代码,如果你是一个有经验的Android程序员,你会更快地完成它。QT会增加bug的几率,因为QT层本身的任何bug都会在你的代码中表现出来。

这个回答本来是作为评论的,但是它的长度很快就超过了限制。对不起:)

c++并没有神奇地比托管语言快。请忽略那些不这么认为的人。

c++所做的就是给你更多的旋钮来玩。如果您不是c++专家,那么在实际应用程序中,您可能会编写出非常不符合习惯的c++代码,其性能远不如简单的Java代码。给你两个具体的例子:初学者倾向于过度使用new(默认情况下,它在c++中的性能很差),他们不明白什么时候隐式复制对象。

如果你投入了必要的时间来深入学习c++(1到10年),一个写得很好的c++程序可以比托管语言中的"对应程序"(如果存在的话)要快得多。

是的,有一些微小的基准测试证明c++比Java快n倍。如果你想要编写这样的基准测试程序,那么学习c++的一个子集是相对容易的。

编写一个微基准测试,显示std::list<T>的性能比java.util.LinkedList<T>差得多,这也是微不足道的。这是因为如果不为std::list<T>节点提供专门的内存分配器,链表将把大部分时间花在内存分配上。这是否意味着c++比Java慢?不,它只是意味着,如果您想成为一名高效的c++程序员,分配器是您必须掌握的旋钮之一。Java程序员并不关心内存来自哪里,因为内存分配在Java中是不可定制的(无论好坏)。

以下是我通过C和Java对whitetstone和Linpack进行基准测试的结果。如果您为特定目标选择了错误的编译选项,编译的C代码可能会变慢,甚至与最佳选项[针对这些类型的CPU基准测试]非常相似。

After results是使用Java几乎与c相同的代码的示例。对于我的Android基准测试,所有使用相同的带有按钮和显示结果的Java前端。如果你需要更多的信息或程序(免费,没有广告)谷歌"罗伊安卓基准。

     ARM v7-A15 rated 2000 MHz but running at 1700 MHz
 Whetstone Benchmark
      MWIPS  ------MFLOPS-------   ------------MOPS--------------
               1      2      3     COS   EXP  FIXPT     IF  EQUAL
Java  533.9  131.4  209.4  102.5  20.4   6.7  475.8  174.8  105.7
C    1477.7  363.9  220.6  307.5  39.7  18.0 1690.5 2527.9 1127.9

Linpack Benchmark MFLOPS
Option     C v5      C v7        C v7       C v7       Java
             DP        DP          SP    NEON SP         DP
          28.82     459.17     803.04    1334.90     143.06

  Example function in C
            startTime = getTime();
            for (ix=0; ix<xtra; ix++)
            {
                for(i=0; i<n1*n1mult; i++)
                {
                    e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
                    e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
                    e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
                    e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
                }
                t = 1.0f - t;
            }
            t =  t0;                    
            endTime = getTime();
            runTime = (endTime - startTime) / 1000.0;

  Example function in Java
            startTime = System.currentTimeMillis();
            for (ix=0; ix<xtra; ix++)
            {
                for(i=0; i<n1*n1mult; i++)
                {
                    e1[0] = (e1[0] + e1[1] + e1[2] - e1[3]) * t;
                    e1[1] = (e1[0] + e1[1] - e1[2] + e1[3]) * t;
                    e1[2] = (e1[0] - e1[1] + e1[2] + e1[3]) * t;
                    e1[3] = (-e1[0] + e1[1] + e1[2] + e1[3]) * t;
                }
                t = 1.0f - t;
            }
            t =  t0;                    
            endTime = System.currentTimeMillis();
            runTime = (endTime - startTime) / 1000.0;