【问题标题】:Groovy performance时髦的表现
【发布时间】:2010-11-05 09:27:10
【问题描述】:

嗨 我们将开始一个 CRUD 项目。 我有一些使用 groovy 和 我认为这是正确的工具。 我关心的是性能。 与 java 解决方案相比,groovy 有多好。 估计我们最多可以有100个 同时用户。我们将使用一个 MySql DB 和一个 tomcat 服务器。

有什么意见或建议吗?

谢谢

【问题讨论】:

  • 为了澄清我的问题,难题是应该采用哪种技术。 Grails 上的 Groovy、Jboss seam 或一些专门开发的东西。对于具有 5ß 到 100 个同时用户的应用程序,Grails 上的 Groovy 性能是否存在问题?
  • 您还需要澄清“同时”。您希望在同一秒内有 100 次操作点击,还是在任何时候都只有 100 次 http 会话? (后者可能意味着每秒点击 5 次)
  • 真的。同时已由我们的客户定义。这意味着多达 100 个用户同时使用该应用程序。 IE。 100 个 http 会话。为您的评论 +1

标签: mysql performance tomcat groovy


【解决方案1】:

我最近收集了五个关于 Groovy 性能的答案的反对票 (!);但是,我认为确实应该需要客观事实。就个人而言,我认为与 Groovy 和 Grails 一起工作是富有成效和乐趣的。然而,有一个需要解决的性能问题。

网络上有许多基准比较,包括this one。你永远不能相信单一的基准(引用的基准甚至不接近科学),但你会明白的。

Groovy 强烈依赖于运行时元编程。例如,Groovy 中的每个对象(除了 Groovy 脚本)都从 GroovyObject 扩展而来,带有 invokeMethod(..) 方法。每次在 Groovy 类中调用方法时,都不会像在 Java 中那样直接调用该方法,而是通过调用前面提到的 invokeMethod(..)(它执行大量反射和查找)。
此外,每个GroovyObject 都有一个关联的MetaClass。方法调用等概念类似。

与 Java 相比,还有其他一些因素会降低 Groovy 的性能,包括原始数据类型的装箱和(可选的)弱类型,但上述运行时元编程的概念至关重要。你甚至无法想到一个带有 Groovy 的 JIT 编译器,它将 Java 字节码编译为本机代码以加快执行速度。

为了解决这些问题,有Groovy++ 项目。您只需用@Typed 注释您的Groovy 类,它们就会静态地 编译成(真正的)Java 字节码。然而不幸的是,我发现 Groovy++ 还不够成熟,并且与 Groovy 主线和 IDE 没有很好的集成。 Groovy++ 也基本的 Groovy 编程范式相矛盾。此外,Groovy++ 的@Typed 注解不会递归地工作,也就是说,不会影响像 GORM 或 Grails 控制器基础设施这样的底层库。

我猜你也在评估使用 Grails 项目。

查看 Grails 的 GORM 时,该框架大量使用运行时元编程,直接使用 Hibernate,性能应该会更好。

在控制器或(尤其是)服务级别,可以将大量计算外化到 Java 类。但是,GORMs 在典型的 CRUD 应用中所占的比例更高。

Grails 中的潜在性能通常通过在database 级别缓存层或通过避免调用服务或控制器方法来解决(请参阅SpringCache pluginCache Filter plugin)。这些通常在Ehcache infrastructure 之上实现。
与经常变化的(数据库)数据或相当多变的 Web 输出相比,缓存显然更适合静态数据。

最后,您可以“向它扔硬件”。 :-)

总之,支持或反对在大型网站中使用 Groovy/Grails 的最决定性因素应该是缓存是否适合特定网站的性质的问题。

编辑: 至于Java的JIT编译器是否有机会介入的问题...
一个简单的 Groovy 类

class Hello {
    def getGreeting(name) {
        "Hello " + name
    }
}

编译成

public class Hello
  implements GroovyObject
{
  public Hello()
  {
    Hello this;
    CallSite[] arrayOfCallSite = $getCallSiteArray();
  }
  public Object getGreeting(Object name) { 
    CallSite[] arrayOfCallSite = $getCallSiteArray(); 
    return arrayOfCallSite[0].call("Hello ", name);
  }

  static
  {
    Long tmp6_3 = Long.valueOf(0L);
    __timeStamp__239_neverHappen1288962446391 = (Long)tmp6_3;
    tmp6_3;
    Long tmp20_17 = Long.valueOf(1288962446391L);
    __timeStamp = (Long)tmp20_17;
    tmp20_17;
    return;
  }
}

这只是冰山一角。活跃的 Groovy 开发人员 Jochen Theodoru 是这样说的:

Groovy 中的方法调用包括 通常有几种正常的方法 调用,存储参数的地方 在一个数组中, 必须检索参数,键是 由它们生成,哈希图是 用于查找方法,如果是 失败,那么我们必须测试 兼容的可用方法 方法,选择其中一种方法 根据运行时类型,创建一个 hasmap 的键,然后在 结束,做一个反射,比如调用 方法。

我真的不认为 JIT 内联了如此动态、高度复杂的调用。

至于您的问题的“解决方案”,没有“那样做就可以了”。相反,任务是确定比其他因素更重要的因素以及可能的替代方案和缓解策略,评估它们对您当前用例的影响(“我可以忍受吗?”),最后,确定组合最能(不完全)满足要求的技术。

【讨论】:

  • 感谢您的回答。我的意思是 Grails 上的 groovy,据我所知,它执行 JIT 编译。然而,如果解决方案是放置更多硬件,那么问题还没有解决。为您的回答 +1。
【解决方案2】:

性能(在 Web 应用程序的上下文中)是您的应用程序的一个方面,而不是您使用的框架/语言的一个方面。任何关于方法调用速度、反射速度和调用经过的框架层数量的讨论和比较都是完全无关的。您没有实现 Photoshop 滤镜、分形或光线追踪器。您正在实施基于 Web 的 CRUD。

您的最佳表现很可能是低效的数据库设计、N+1 查询(如果您使用 ORM)、全表扫描等。

回答您的问题:使用任何您觉得更有信心的现代语言/网络框架,并专注于正确的架构/设计来解决手头的业务问题。

【讨论】:

  • 我不同意语言/框架无关紧要。我没有任何数据来支持这一点,但是大量使用反射的动态语言会对性能产生影响,并且当系统有很多用户时,这种影响会成倍增加。同一个简单的 CRUD 应用程序在用 Java 编写时可能比用动态语言编写时能够处理更多的用户。
  • 方法调用比 I/O(文件访问、网络访问、数据库操作)快几个数量级。因此,对于 webapps,它不会发挥任何作用,Java 可能会在 4 个 nanos 中执行运行时调度,而 ruby​​ 在 40 个中执行。担心这是错误的方向。
【解决方案3】:

感谢您的回答和建议。我喜欢时髦的。在某些情况下可能会出现一些性能问题。 Groovy++ 可能是更好的选择。在他的观点上,我更愿意给“spring roo”一个机会,它与 Groovy 有很大的重叠,但你仍然在 java 并且没有 roo.jar 被添加到你的项目中。因此,您无需为使用它支付任何额外费用。 此外,“roo”允许反向工程和往返工程。 不幸的是,到目前为止,插件库还很小。

路易斯

【讨论】:

【解决方案4】:

50 到 100 个活跃用户的流量并不大。只要你有正确的缓存页面,mysql查询是正确的索引,你应该没问题。

这是我在地下室中运行的一个站点,它的服务器价格为 1000 美元。它是用 Grails 编写的。 自己检查性能http://www.ewebhostguide.com

警告:有时 Comcast 连接已关闭,网站可能会出现关闭。但这只会发生几分钟。在地下室运行站点的缺点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 2016-12-12
    • 2011-12-11
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    相关资源
    最近更新 更多