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

时间:2014-07-13 04:51:05

标签: android c++ performance qt qt5

针对在Qt上使用C ++编写的Android设备的应用程序是否会比使用Android SDK使用Java编写的应用程序执行得更好?

4 个答案:

答案 0 :(得分:11)

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

首先,用Java实现Android SDK,因此开发人员应该使用Java作为默认值。

更多性能和更多控制

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

Android使用名为 Dalvik 的特定虚拟机(直到第5版)。任何需要UI的应用程序都需要Dalvik。所以C ++应用程序(游戏和Qt等)需要涉及Dalvik。

此外,没有C ++库直接从C ++(如联系簿)中使用服务和操作系统功能。因此,您需要将Java与C ++一起使用。为此,您需要在.java文件中编写一些Java代码,并且需要使用JNI来进行C ++和Java的通信。 JNI是另一个你需要学习的问题 因此,使用C ++开发Android应用程序比使用常规Java应用程序要困难得多 。

我在Android上的Qt体验

我在没有QtQuick Controls的情况下编写了Qt \ QtQuick的一些Android应用程序。 QtQuick对于UI开发来说非常棒,但您需要做一些事情,例如手动管理加载和卸载UI。这不是问题,因为QtQuick中有一些功能用于此目的,如Loader 在Desktop中实现应用程序的一般部分(非特定于Android部分)非常高效,快速且有趣(包括C ++和QtQuick)。
但是在JNI中实现Android特定部分需要更多时间和关注。

Qt on Android - 缺点和优点

  • APK包很大(大多数情况下约为8mb)
  • 需要发布多个APK包(ARM,x86)(Google Play让您在没有最终用户注意的情况下做得非常好)
  • 应用启动时间高于普通应用
  • 需要通过JNI
  • 使用C ++和Java的组合开发
  • 调试更困难
  • 更少的文档
  • 极其 快速用户界面
  • 如果您计划在iOS等其他平台上发布您的应用,则只需重新实现特定于操作系统的部分。因此,您的时间/成本将会降低。
  • 高性能后端处理和整体应用性能
  • 更好的记忆管理
  • Android 2.2中的相同质量(例如)直到7.0! (Android SDK的某些功能只是更高版本,因此如果您计划支持较低版本的Android,则无法使用该功能。例如AnimationFramework。使用Qt您没有此问题)
  • 在早期Android版本及更高版本中使用硬件加速UI
  • 防止取消复制的源代码保护
  • 关于视图和模型/控制器的良好分离(帮助专业编码)
  • 简单快速的UI开发
  • 轻松美观的UI效果(OpenGLES& GLSL)(也自然地集成到UI的其他组件中)

建议

IF(您不是Qt经验丰富的开发人员)=>使用Java

IF(某些处理需要更多性能)=> Java + C ++(NDK)

IF(您是Qt经验丰富的开发人员)和((您是Java初学者)或(您计划将应用移植到其他平台))=>将Qt与C ++一起使用

答案 1 :(得分:2)

让我们将其分为两部分:

1)C ++会比Java更好吗?

是。当然会的。它总是这样,只要你不让许多JNI调用回Java。这就是为什么人们(包括谷歌)在性能至关重要的情况下使用C ++的原因。

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

假设您以最佳方式编写两种代码,则订单可能是原始NDK调用> Java调用> QT电话。 QT库只是要进行完全相同的函数调用,它只是在其上放置一个不同的抽象层。该层将增加开销。有可能在大多数情况下开销很小。如果您是经验丰富的QT程序员,您可能会使用QT更快地编码。如果您是一名经验丰富的Android程序员,那么如果没有它,您可以更快地完成它。 QT会增加错误的几率,因为QT层中的任何错误都会在你的代码中显示出来。

答案 2 :(得分:1)

这个答案仅作为评论,但其长度很快就超出了限制。对不起:)

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中自定义(无论好坏)。

答案 3 :(得分:0)

以下是我的Whetstone和Linpack基准测试通过C和Java的结果。如果为特定目标选择了错误的编译选项,或者使用最佳选项[对于这些类型的CPU基准测试],编译的C代码可能会更慢。

结果是使用的代码示例,其中Java几乎与C相同。对于我的Android基准测试,所有人都使用相同的Java前端和按钮并显示结果。如果您需要更多信息或程序(免费,没有广告)谷歌的“罗伊Android基准测试。

     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;