https://groups.google.com/forum/#!topic/seastar-dev/RuK-OajeqHk

https://www.google.com/search?ei=gTH-Wtr5O4WQsAW-io7wCQ&q=dl_iterate_phdr+gcc+exception&oq=dl_iterate_phdr+gcc+exception&gs_l=psy-ab.3...5055.7797.0.8041.10.8.0.0.0.0.382.997.3-3.3.0....0...1.1.64.psy-ab..7.1.306...33i160k1.0.dDZSKQ-pAA4

g++/glibc combination provides a c++ runtime with non scaleable 
c++ exception. This is dues to global locks in stack unwinding code. 
    
To summarize all the locks we have now and their purpose: 
 1. There is a lock in _Unwind_Find_FDE (libgcc) that protects 
    list of FDEs registered with __register_frame* functions. 
    The catch is that dynamically linked binary do not do that, 
    so all that it protects is checking that a certain list is empty. 
    This lock no longer relevant in gcc7 since there is a path there 
    checks that list is empty outside of the lock. 
 2. The lock in dl_iterate_phdr (glibc) that protects loaded object 
    list against runtime object loading/unloading.

To get rid of the first lock one has to use gcc7.

To get rid of the second one we can use the fact that we do not 
load/unload objects dynamically (at least for now). To do that we 
can mirror all elf header information in seastar and provide our 
own dl_iterate_phdr symbol which uses this mirror without locking. 
    
Unfortunately there is another gotcha in this approach: dl_iterate_phdr 
supplied by glibc never calls more then one callback simultaneously as an 
unintended consequences of the lock there, but unfortunately libgcc relies 
on that to maintain small cache of translations. The access to the cache is 
not protected by any lock since up until now only one callback could have 
run at a time. But luckily libgcc cannot use the cache if older version 
of dl_phdr_info is provided to the callback because the older version 
did not have an indication that loaded object list may have changed, 
so libgcc does not know when cache should be invalidated and disables it 
entirely. By calling the callback with old version of dl_phdr_info from 
our dl_iterate_phdr we can effectively make libgcc callback thread safe.

diff --git a/configure.py b/configure.py 
index facdd8f..33b310b 100755 
--- a/configure.py 
+++ b/configure.py 
@@ -297,6 +297,8 @@ arg_parser.add_argument('--static-boost', dest = 'staticboost', action = 'store_ 
 add_tristate(arg_parser, name = 'hwloc', dest = 'hwloc', help = 'hwloc support') 
 arg_parser.add_argument('--enable-gcc6-concepts', dest='gcc6_concepts', action='store_true', default=False, 
                         help='enable experimental support for C++ Concepts as implemented in GCC 6') 
+arg_parser.add_argument('--disable-exception-scalability-workaround', dest='exception_workaround', action='store_true', default=False, 
+        help='disabling override of dl_iterate_phdr symbol to workaround C++ exception scalability issues') 
 args = arg_parser.parse_args() 
  
 libnet = [ 
@@ -337,6 +339,7 @@ core = [ 
     'net/inet_address.cc', 
     'rpc/rpc.cc', 
     'rpc/lz4_compressor.cc', 
+    'core/exception_hacks.cc', 
     ] 
  
 protobuf = [ 
@@ -392,6 +395,9 @@ if args.gcc6_concepts: 
     defines.append('HAVE_GCC6_CONCEPTS') 
     args.user_cflags += ' -fconcepts' 
  
+if args.exception_workaround: 
+    defines.append('NO_EXCEPTION_HACK') 
+ 
 if args.staticcxx: 
     libs = libs.replace('-lstdc++', '') 
     libs += ' -static-libgcc -static-libstdc++' 
diff --git a/core/exception_hacks.cc b/core/exception_hacks.cc 
new file mode 100644 
index 0000000..6f04630 
--- /dev/null 
+++ b/core/exception_hacks.cc 
@@ -0,0 +1,108 @@ 
+/* 
+ * This file is open source software, licensed to you under the terms 
+ * of the Apache License, Version 2.0 (the "License").  See the NOTICE file 
+ * distributed with this work for additional information regarding copyright 
+ * ownership.  You may not use this file except in compliance with the License. 
+ * 
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0 
+ * 
+ * Unless required by applicable law or agreed to in writing, 
+ * software distributed under the License is distributed on an 
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
+ * KIND, either express or implied.  See the License for the 
+ * specific language governing permissions and limitations 
+ * under the License. 
+ */ 
+/* 
+ * Copyright (C) 2017 ScyllaDB 
+ */ 
+ 
+// The purpose of the hacks here is to workaround C++ exception scalability problem 
+// with gcc and glibc. For the best result gcc-7 is required. 
+// 
+// To summarize all the locks we have now and their purpose: 
+// 1. There is a lock in _Unwind_Find_FDE (libgcc) that protects 
+//    list of FDEs registered with __register_frame* functions. 
+//    The catch is that dynamically linked binary do not do that, 
+//    so all that it protects is checking that a certain list is empty. 
+//    This lock no longer relevant in gcc-7 since there is a path there 
+//    that checks that list is empty outside of the lock and it will be 
+//    always true for us. 
+// 2. The lock in dl_iterate_phdr (glibc) that protects loaded object 
+//    list against runtime object loading/unloading. 
+// 
+// To get rid of the first lock using gcc-7 is required. 
+// 
+// To get rid of the second one we can use the fact that we do not 
+// load/unload objects dynamically (at least for now). To do that we 
+// can mirror all elf header information in seastar and provide our 
+// own dl_iterate_phdr symbol which uses this mirror without locking. 
+// 
+// Unfortunately there is another gotcha in this approach: dl_iterate_phdr 
+// supplied by glibc never calls more then one callback simultaneously as an 
+// unintended consequences of the lock there, but unfortunately libgcc relies 
+// on that to maintain small cache of translations. The access to the cache is 
+// not protected by any lock since up until now only one callback could have 
+// run at a time. But luckily libgcc cannot use the cache if older version 
+// of dl_phdr_info is provided to the callback because the older version 
+// did not have an indication that loaded object list may have changed, 
+// so libgcc does not know when cache should be invalidated and disables it 
+// entirely. By calling the callback with old version of dl_phdr_info from 
+// our dl_iterate_phdr we can effectively make libgcc callback thread safe. 
+ 
+#ifndef NO_EXCEPTION_HACK 
+#include <link.h> 
+#include <dlfcn.h> 
+#include <assert.h> 
+#include <vector> 
+#include <cstddef> 
+#include "exception_hacks.hh" 
+ 
+namespace seastar { 
+using dl_iterate_fn = int (*) (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data); 
+ 
+static dl_iterate_fn dl_iterate_phdr_org() { 
+    static dl_iterate_fn org = [] { 
+        auto org = (dl_iterate_fn)dlsym (RTLD_NEXT, "dl_iterate_phdr"); 
+        assert(org); 
+        return org; 
+    }(); 
+    return org; 
+} 
+ 
+static std::vector<dl_phdr_info> phdrs_cache; 
+ 
+void init_phdr_cache() { 
+    // Fill out elf header cache for access without locking. 
+    // This assumes no dynamic object loading/unloading after this point 
+    dl_iterate_phdr_org()([] (struct dl_phdr_info *info, size_t size, void *data) { 
+        phdrs_cache.push_back(*info); 
+        return 0; 
+    }, nullptr); 
+} 
+} 
+ 
+extern "C" 
+[[gnu::visibility("default")]] 
+[[gnu::externally_visible]] 
+int dl_iterate_phdr(int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data) { 
+    if (!seastar::phdrs_cache.size()) { 
+        // Cache is not yet populated, pass through to original function 
+        return seastar::dl_iterate_phdr_org()(callback, data); 
+    } 
+    int r = 0; 
+    for (auto h : seastar::phdrs_cache) { 
+        // Pass dl_phdr_info size that does not include dlpi_adds and dlpi_subs. 
+        // This forces libgcc to disable caching which is not thread safe and 
+        // requires dl_iterate_phdr to serialize calls to callback. Since we do 
+        // not serialize here we have to disable caching. 
+        r = callback(&h, offsetof(dl_phdr_info, dlpi_adds), data); 
+        if (r) { 
+            break; 
+        } 
+    } 
+    return r; 
+} 
+#endif 
diff --git a/core/exception_hacks.hh b/core/exception_hacks.hh 
new file mode 100644 
index 0000000..f5ff51f 
--- /dev/null 
+++ b/core/exception_hacks.hh 
@@ -0,0 +1,24 @@ 
+/* 
+ * This file is open source software, licensed to you under the terms 
+ * of the Apache License, Version 2.0 (the "License").  See the NOTICE file 
+ * distributed with this work for additional information regarding copyright 
+ * ownership.  You may not use this file except in compliance with the License. 
+ * 
+ * You may obtain a copy of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0 
+ * 
+ * Unless required by applicable law or agreed to in writing, 
+ * software distributed under the License is distributed on an 
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
+ * KIND, either express or implied.  See the License for the 
+ * specific language governing permissions and limitations 
+ * under the License. 
+ */ 
+/* 
+ * Copyright (C) 2017 ScyllaDB 
+ */ 
+ 
+namespace seastar { 
+void init_phdr_cache(); 
+} 
diff --git a/core/reactor.cc b/core/reactor.cc 
index 2beef59..b4b4e8d 100644 
--- a/core/reactor.cc 
+++ b/core/reactor.cc 
@@ -93,6 +93,7 @@ 
 #include "util/defer.hh" 
 #include "core/metrics.hh" 
 #include "execution_stage.hh" 
+#include "exception_hacks.hh" 
  
 namespace seastar { 
  
@@ -3369,6 +3370,9 @@ smp::get_options_description() 
         ("max-io-requests", bpo::value<unsigned>(), "Maximum amount of concurrent requests to be sent to the disk. Defaults to 128 times the number of processors") 
 #endif 
         ("mbind", bpo::value<bool>()->default_value(true), "enable mbind") 
+#ifndef NO_EXCEPTION_HACK 
+        ("enable-glibc-exception-scaling-workaround", bpo::value<bool>()->default_value(true), "enable workaround for glibc/gcc c++ exception scalablity problem") 
+#endif 
         ; 
     return opts; 
 } 
@@ -3514,6 +3518,12 @@ static void sigabrt_action() noexcept { 
  
 void smp::configure(boost::program_options::variables_map configuration) 
 { 
+#ifndef NO_EXCEPTION_HACK 
+    if (configuration["enable-glibc-exception-scaling-workaround"].as<bool>()) { 
+        init_phdr_cache(); 
+    } 
+#endif 
+ 
     // Mask most, to prevent threads (esp. dpdk helper threads) 
     // from servicing a signal.  Individual reactors will unmask signals 
     // as they become prepared to handle them. 
-- 
                        Gleb.

C++ 的 runtime exception是没有扩展性的的更多相关文章

  1. 优秀开源项目之三:高性能、高并发、高扩展性和可读性的网络服务器架构State Threads

    译文在后面. State Threads for Internet Applications Introduction State Threads is an application library ...

  2. Atitit.兼具兼容性和扩展性的配置方案attilax总结

    Atitit.兼具兼容性和扩展性的配置方案attilax总结 文件配置法1 Jdbc多数据源文件配置发1 Bat文件配置法1 改进的文件配置法(采用类似i18n技术) 推荐1 使用自动化pc_id的方 ...

  3. Atitit.软件架构高扩展性and兼容性原理与概论实践attilax总结

    Atitit.软件架构高扩展性and兼容性原理与概论实践attilax总结 1. 什么是可扩展的应用程序?1 2. 松耦合(ioc)2 3. 接口的思考 2 4. 单一用途&模块化,小粒度化2 ...

  4. OpenStack 企业私有云的若干需求(6):大规模扩展性支持

    本系列会介绍OpenStack 企业私有云的几个需求: 自动扩展(Auto-scaling)支持 多租户和租户隔离 (multi-tenancy and tenancy isolation) 混合云( ...

  5. 使用Lua脚本语言开发出高扩展性的系统,AgileEAS.NET SOA中间件Lua脚本引擎介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  6. jetbrick,新一代 Java 模板引擎,具有高性能和高扩展性

    新一代 Java 模板引擎,具有高性能和高扩展性. <!-- Jetbrick Template Engineer --> <dependency> <groupId&g ...

  7. Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文主要介绍一个支持图片自动预取.支持多种缓存算法的图片缓存的使用及功能.图片较大需要SD卡保存情况推荐使用ImageSDCardCache. 与Android LruCache相比主要特性:(1). ...

  8. Checked Exception与Runtime Exception 的区别

    Java里有个很重要的特色是Exception ,也就是说允许程序产生例外状况.而在学Java 的时候,我们也只知道Exception 的写法,却未必真能了解不同种类的Exception 的区别. 首 ...

  9. 深入NGINX:我们如何设计它的性能和扩展性

    为了更好地理解设计,你需要了解NGINX是如何工作的.NGINX之所以能在性能上如此优越,是由于其背后的设计.许多web服务器和应用服务器使用简单的线程的(threaded).或基于流程的 (proc ...

随机推荐

  1. Material Designer的低版本兼容实现(四)—— ToolBar

       Toolbar其实是一个ActionBar的变体,大大扩展了Actionbar.我们可以像对待一个独立控件一样去使用ToolBar,可以将它放到屏幕的任何位置,不必拘泥于顶部,还可以将它改变高度 ...

  2. SSO单点登录之Asp.Net实现示例

    一.什么是单点登录SSO(Single Sign-On) SSO是一种统一 认知 和授权机制,指访问用同一服务器不同应用中的受保护资源的同一用户,只需登录一次,即通过一个应用中的安全验证 后,再访问其 ...

  3. 再有人问你Java内存模型是什么,就把这篇文章发给他

    前几天,发了一篇文章,介绍了一下JVM内存结构.Java内存模型以及Java对象模型之间的区别.有很多小伙伴反馈希望可以深入的讲解下每个知识点.Java内存模型,是这三个知识点当中最晦涩难懂的一个,而 ...

  4. C#7.0新增功能点

    原文地址:  https://www.cnblogs.com/runningsmallguo/p/8972678.html 第二部分:C#7.0新增的功能 (1)数字字面量的提升: C#7中的数字文字 ...

  5. 用SLF4j/Logback打印日志-2

    本篇主要介绍logback的输出源配置,logback默认提供了很多输出源,但是用的最多的是这几种: OutputStreamAppender 日志输出到一个二进制流,可以通过 <encoder ...

  6. iOS:创建带logol的二维码

    //二维码生成 实质: 把字符串转变为 图片 // 需要 coreImage框架, 已经包含在了 UIKit框架里面 //MARK: 二维码中间内置图片,可以是公司logo + (UIImage *) ...

  7. scp命令:服务器间远程复制代码

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...

  8. knockout示例

    最近项目需要用到knockout js,有关knockout的介绍网上已经很多很多了,但是很少有比较全面的示例,于是乎我就自己做了一个小demo,已备以后查阅.knockout经常和knockout. ...

  9. 组件化 得到 DDComponent JIMU 模块 插件 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  10. Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class

    [背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...