0

我有一个用 C 编写的非托管库(它在内部也使用英特尔 MKL 库),用于 WCF Web 服务。直接 PInvoke 用于调用公开的方法,库调用返回一个指向双精度数组的指针,该双精度数组在调用指针上的 free() 之前复制到 C# 中的托管数组。

        double* xStars = null;
        metaData meta = new metaData();
        double[] output = null;
        bool hasError;
        string errorMessage;
        try
        {
            int errCode = someCFunction(...some params...
                &xStars,
                &meta);

            output = new double[meta.ArrayLength];
            for (int j = 0; j < meta.ArrayLength; j++)
            {
                output[j] = (xStars[j]);
            }
        }
        catch (Exception e)
        {
            WriteToEventLog();
            throw;
        }
        finally
        {
                            //Also in the C library
                            //Calls free(void *) 
            freeDoubleArray(&xStars);
            freeMeta(&meta);
        }

我有测试套件可以通过调用它

  • IIS 作为 Web 服务调用或
  • 运行所有其他业务逻辑但不作为 WS 运行的控制台应用程序
  • 一个较小的控制台应用程序,它只是练习执行 PInvoke 的类

  • 通过控制台应用程序 (2) 运行时,使用的启动内存约为 50MB,即使在循环调用底层 C 代码 100 次后仍保持相当稳定

  • 通过控制台应用程序(2)运行时,启动内存更小,大约 24MB,并且在 100 次调用后保持稳定
  • 通过 IIS 运行时,即使在服务启动时,内存使用量也在 150-200 MB 左右,并且每次调用 C 库时都会不断增加。它最终达到了 IIS 回收它的地步,因为正在使用的内存超出了设置的限制

它在 IIS 中的使用方式有什么问题?控制台应用程序 (2) 基本上是所有代码,但只是作为独立应用程序而不是 Web 服务运行。在这种情况下,应用程序不会出现任何内存泄漏或过度使用。

到目前为止,我为了解根本原因所做的事情:

  1. 使用性能监视器来分析所有堆中的私有字节和 GC 字节。托管内存使用量在进程启动时上升,并且在整个测试过程中几乎保持一条直线,而私有字节使用量在第一次调用时飙升至 100 MB,并且在每次测试迭代中保持略微增加。
  2. 使用 Debug Diag 来分析非托管内存泄漏和 IIS 工作进程使用的 500 MB,Debug diag 表明 C 库有大约 43 MB 的未释放内存,它认为这是一个泄漏,但没有解释其余的在哪里用过的
  3. 我使用了 ANTS 内存分析器,它表明大部分内存是非托管的,托管内存使用量最差,在 30 MB 以内。

我想我没有足够的代表点来发布图片,或者我可以发布性能监视器的屏幕截图。编写 C 代码的人认为这是一个 IIS 问题(或与 Web 服务 C# 代码有关),并指出在独立应用程序中使用时,没有任何明显的泄漏。我使用的调试工具似乎另有说明。

有什么建议可以帮助我确定问题出在哪里?

4

1 回答 1

1

如果 ANTS 内存分析器已确定将“主要块”内存分配给您预计不会使用非托管内存的非托管代码,那么这将是开始调查的好地方。

如果取消注释“freeDoubleArray(&xStars);”会发生什么 和“freeMeta(&meta);”?您在控制台应用程序中是否获得与 ISS Web 服务类似的行为?

如果在 finally 块的末尾强制进行 GC 收集会发生什么?您的 ISS Web 服务的行为方式是否与您的控制台应用程序类似?

于 2013-08-22T21:57:50.977 回答