首页 > 解决方案 > Ada, Gnat:与 pthread 相比,受保护类型 + 条目的效率如何?

问题描述

问题是关于在 Linux 上使用 GNAT 编译器的受保护类型和条目的性能。Mutex 仅作为示例使用(Ada 不需要)。

我将来自 Rosetta Code ( https://rosettacode.org/wiki/Mutex#Ada )的 Ada Mutex 实现的性能与使用 import 和 C 接口从 Ada 调用的非常简单的 C/pthread 实现进行了比较。

事实证明,Ada 保护类型 + 条目慢了 36.8 倍。我知道 GNAT 可能会通过它的运行时库并最终调用操作系统原语 sa pthread。我排除了一些开销,但没有那么多。

问题是:为什么?

以防万一 - 这是我的简单 pthread 实现:

     -- cmutex.ads

     package CMutex is
        procedure  Lock with
            Import => True,
            Convention => C,
            External_Name => "mutex_lock";

        procedure Unlock with
            Import => True,
            Convention => C,
            External_Name => "mutex_unlock";
    end CMutex;
    // C code
    #include <pthread.h>

    static  pthread_mutex_t mtx     = PTHREAD_MUTEX_INITIALIZER;

    void mutex_lock()
    {
        pthread_mutex_lock(&mtx);
    }

    void mutex_unlock()
    {
        pthread_mutex_unlock(&mtx);
    }

==== 编辑 ===

添加最少的可指责代码。它是单线程(仅用于测试),虚拟变量是为了防止优化器优化整个循环。

上面pthread(cmutex)的测试代码是:

with Text_IO; use Text_IO;
with CMutex;
procedure test is
   dummy : Integer := 0;
begin
    for i in 1 .. 100_000_000 loop
        CMutex.Lock;
        dummy := dummy + 1;
        CMutex.Unlock;
    end loop;
    Text_IO.Put_Line(Integer'image(dummy));
end test;

保护类型+入口示例的测试代码为:

with Text_IO; use Text_IO;
with Ada_Mutex;
procedure test1 is
   dummy : Integer := 0;
   mtx   : Ada_Mutex.Mutex;
begin
    for i in 1 .. 100_000_000 loop
        mtx.Seize;
        dummy := dummy + 1;
        mtx.Release;
    end loop;
    Text_IO.Put_Line(Integer'image(dummy));
end test1;

其中 Ada_Mutex 是一个包含示例表单 Rosetta 代码的包:

package Ada_Mutex is
protected type Mutex is
   entry Seize;
   procedure Release;
private
   Owned : Boolean := False;
end Mutex;
end Ada_mutex;
--------------------------------
package body Ada_Mutex is
   protected body Mutex is
      entry Seize when not Owned is
      begin
         Owned := True;
      end Seize;
      procedure Release is
      begin
         Owned := False;
      end Release;
   end Mutex;
end Ada_Mutex;

使用 pthread 互斥锁的代码的运行时间是(在英特尔 NUC i7 中):

$时间./测试

 100000000

 real   0m0.557s
 user   0m0.553s
 sys    0m0.005s

以及使用受保护类型和条目的代码: $ time ./test1

  100000000

  real  0m19.009s
  user  0m19.005s
  sys   0m0.005s

没有优化 (-O0) 的时间是:

real    0m0.746s
user    0m0.746s
sys     0m0.000s

real    0m20.173s
user    0m20.172s
sys     0m0.000s

分别用于 pthread 和受保护的类型+条目。

注意用户时间~=实时,这意味着处理器很忙(它没有空闲,或者以其他方式让出控制)

标签: ada

解决方案


推荐阅读