受 SQLite 多年青睐,C 语言到底好在哪儿?

640?wx_fmt=gif

SQLite 近日发表了一篇博文,解释了为什么多年来 SQLite 一直坚持用 C 语言来实现,以下是正文内容:

640?wx_fmt=jpeg


640?wx_fmt=png

C 语言是最佳选择


从 2000 年 5 月 29 日发布至今,SQLite 一直都是用 C 语言实现。C 一直是实现像 SQLite 这类软件库的最佳语言。目前,还没有任何计划要采用另外一门语言对 SQLite 进行重新开发。

为什么 C 语言是实现 SQLite 的最佳选择?原因主要体现在这几个方面:

  • 性能

  • 兼容性

  • 低依赖性

  • 稳定性


640?wx_fmt=png

性能


像 SQLite 这类库要求速度必须要快。SQLite 的速度就很快,它比文件系统快 35%(详情可以参考这两个示例:Internal Versus External BLOBs 和 35% Faster Than The Filesystem)。

而 C 语言就能实现快速编写代码。C 语言通常被描述为“可移植性的汇编语言”。它使开发人员能够尽可能靠近底层硬件进行编码,同时仍然可以跨平台保持可移植性。

平常,我们可能会看到有人描述某种语言“像 C 语言一样快”,却不会看到有人说,作为通用目的编程时,会有一门语言“比 C 语言快”,因为这种语言真的不存在。


640?wx_fmt=png

兼容性


几乎所有系统都能调用 C 语言编写的库,但其他语言就不尽然。例如,用 Java 编写的 Android 应用能够调用 SQLite(通过适配器)。 如果用 Java 编写 SQLite,那么对 Android 来说可能会更方便,因为这会使接口更简单。但在 iPhone 上,应用程序是用 Objective-C 或 Swift 编写的,它们都不能调用用 Java 编写的库。 因此,如果用 Java 编写,SQLite 将无法在 iPhone 上使用。


640?wx_fmt=png

低依赖性


用 C 语言编写的库对运行时没有很强的依赖。SQLite 的最低配置也只要求 C 库中的这些方法:

  • memcmp()

  • memcpy()

  • memmove()

  • memset()

  • strcmp()

  • strlen()

  • strncmp()

在更完整的构建中,SQLite 也使用诸如 malloc() 和 free() 之类的库例程以及用于打开,读取,写入和关闭文件的操作系统接口。 但即便如此,依赖的数量也很少。


640?wx_fmt=png

稳定性


C 语言易于理解,契合了 SQLite 的要求,适合 SQLite 的开发。


640?wx_fmt=png

为什么 SQLite 不使用面向对象的语言?


开发人员可能无法想象用“非面向对象”来开发一个像 SQLite 这样复杂的系统会是什么样子。所以 SQLite 为什么不使用 C++ 或者 Java 来开发呢?

  1. 用 C++ 或 Java 编写的库通常只能由以相同语言编写的应用程序使用。 使用 Haskell 或 Java 编写的应用程序很难调用用 C++ 编写的库。 另一方面,用 C 语言编写的库可以从任何编程语言调用。

  2. 面向对象是设计模式,而不是编程语言。 你可以使用任何所需语言(包括汇编语言)进行面向对象编程。 某些语言(例如:C++ 或 Java)可以使面向对象更容易,但你仍然可以用像 C 这样的语言进行面向对象的编程。

  3. 面向对象不是唯一有效的设计模式。对象通常是分解问题的好方法。 但不是唯一的方法,也不总是分解问题的最佳方法。 有时好的旧程序代码更容易编写,更易于维护和理解,并且比面向对象的代码更快。

  4. SQLite 进行开发时,Java 还不是一门成熟的语言,C++ 会成熟一点,但当时要找到两种能以 相同方式工作的 C++ 编译器比较困难。相比之下,C 语言是个不错的选择。虽然,这种情况现在有所改善,但为此对 SQLite 重新开发并没有什么好处。


640?wx_fmt=png

为什么 SQLite 不使用"安全"语言编写?


使用“安全”语言不易发生内存泄露、数组溢出等的安全问题。最近,许多人好像对 Rust 和 Go 这样的“安全”语言感兴趣。但 SQLite 为什么不使用呢?

  1. SQLite 出现后的 10 年时间里,所谓的“安全”语言还不存在。虽然 SQLite 可以用 Rust 或者 Go 重新编写,但这样可能会引入更多难以修复的 Bug,进而会影响编码速度。

  2. “安全”编程语言解决简单的问题:像内存泄露、数组溢出等。在解决 SQL 计算结果这类的问题上,并不如 C 语言好用。

  3. “安全”语言可防止安全漏洞,但 SQLite 并非一个对安全敏感的库。如果应用运行了不受信任的 SQL,那它可能已经存在更大的安全问题,而这是“安全”语言无法修复的问题。

  4. 一些“安全”语言(如 Go 语言)不喜欢使用 assert(),但这是保持 SQLite 可维护性的重要前提。

  5. “安全”语言会插入额外的机器分支来执行其他操作。但在正确的代码中,这些分支并不会被采用。所以机器代码不能 100% 被测试到,可这恰恰是 SQLite 质量检测的重要组成部分。

  6. “安全”语言会在内存不足(OOM)时请求终止,而 SQLite 的设计是遇到 OOM 时能重新恢复。目前,还不知道如何利用“安全”语言实现这一点。

  7. 现有的“安全”语言都比较新,SQLite 开发员对它们的出现表示赞赏,但依然认为 C 语言更适合目前的开发工作。

文章最后表示,SQLite 可能会考虑使用 Rust 重新开发,但不太可能使用 Go 语言,因为它对 assert() 不友好。但其实 Rust 目前的条件并不足以对 SQLite 进行重新开发,它还需要继续发展,详情请查看原文。

原文:https://sqlite.org/whyc.html

编译:开源中国

640?wx_fmt=jpeg


征稿啦

CSDN 公众号秉持着「与千万技术人共成长」理念,不仅以「极客头条」、「畅言」栏目在第一时间以技术人的独特视角描述技术人关心的行业焦点事件,更有「技术头条」专栏,深度解读行业内的热门技术与场景应用,让所有的开发者紧跟技术潮流,保持警醒的技术嗅觉,对行业趋势、技术有更为全面的认知。

如果你有优质的文章,或是行业热点事件、技术趋势的真知灼见,或是深度的应用实践、场景方案等的新见解,欢迎联系 CSDN 投稿,联系方式:微信(guorui_1118,请备注投稿+姓名+公司职位),邮箱(guorui@csdn.net)。


————— 推荐阅读 —————

640?wx_fmt=png640?wx_fmt=png640?wx_fmt=png

640?wx_fmt=gif

640?wx_fmt=gif

展开阅读全文

桌面虚拟化与服务器虚拟化同受青睐

10-12

rn众所周知,服务器虚拟化在近几年已成为企业在实施虚拟化部署方面的主流,但在企业通过使用和不断认识的前提下,桌面虚拟化以越来越多的利益更强的安全性、更高灵活性和几乎为零宕机的维护得到了企业IT经理们的青睐。rn服务器虚拟化同桌面虚拟化的不同在于桌面虚拟化是在服务器虚拟化后把本地的运算移交给了服务器,每个桌面应用是服务器虚拟化出的桌面,没有物理化硬件,而只是人机交互所产生的镜像,更不是众多用户使用同一个桌面,每个人用的是自己独有的桌面,在PC、平板、智能手机或瘦客户机等设备上使用,与在本地使用的体验相同。当然这还需要有设备所在地的网络的支持。同样在云计算的模式下,数据是统一存储在数据中心点,任何使用者的设备上运行的是数据中心程序,移动和安全的到了体现,这更适合于远程及跨省的分公司和出差使用。rn而服务器虚拟化是把物理的服务器虚拟化若干个虚拟的服务器,统一运算分配给不同的用户,在多个物理服务器之上虚拟出的更多的虚拟服务器组成一个资源池进行存储和备份,并能是在一个服务器出现问题的情况下,进行动态迁移保障任务的持续,节省空间。但服务器不能像桌面一样随时随地的移动,保证了数据安全,也就有了本身局限。rn服务器虚拟化和桌面虚拟化是相辅相成的,在采用服务器虚拟化的同时应及时考虑企业的用途,桌面虚拟化在当下也是必不可少的了。它可以让IT团队从耗时任务管理中头里出来,不再考虑安全和维护,而集中精力提高工作效率,利用桌面虚拟化的高度的灵活性、高可控性和服务器虚拟化的高可用为企业创造更多的价值。rn推荐阅读:桌面虚拟化 rn 论坛

这段代码到底哪儿错了?

09-09

<%rnstrSourceFile=Server.MapPath("/")&"\List.xml"rnSetobjXML=Server.CreateObject("Microsoft.FreeThreadedXMLDOM")rnobjXML.load(strSourceFile)rnSet objRootsite=objXML.documentElement.selectSingleNode("NewList")rn%>rnrnrn 留言本rn rn rnrnrn|AllNodesNum thenrnEndNodes=EndNodes-(StarNodes-AllNodesNum)rnStarNodes=AllNodesNumrnend ifrnif EndNodes<0 thenrnEndNodes=0rnend ifrnwhile StarNodes>=EndNodesrnusername = objRootsite.childNodes.item(StarNodes).childNodes.item (1).textrnfromwhere = objRootsite.childNodes.item(StarNodes).childNodes.item (2).textrnPosttime = objRootsite.childNodes.item(StarNodes).childNodes.item (3).textrnhomepage = objRootsite.childNodes.item(StarNodes).childNodes.item (4).textrnemail=objRootsite.childNodes.item(StarNodes).childNodes.item (5).textrntext=objRootsite.childNodes.item(StarNodes).childNodes.item (6).textrnText=replace(text,chr(32),"")rn%>rn||信箱||留言时间:<%=Posttime%>|rn rn <%=text%> 主页 rn rn 留言本AllNodesNum thenrnEndNodes=EndNodes-(StarNodes-AllNodesNum)rnStarNodes=AllNodesNumrnend ifrnif EndNodes<0 thenrnEndNodes=0rnend ifrnwhile StarNodes>=EndNodesrnusername = objRootsite.childNodes.item(StarNodes).childNodes.item (1).textrnfromwhere = objRootsite.childNodes.item(StarNodes).childNodes.item (2).textrnPosttime = objRootsite.childNodes.item(StarNodes).childNodes.item (3).textrnhomepage = objRootsite.childNodes.item(StarNodes).childNodes.item (4).textrnemail=objRootsite.childNodes.item(StarNodes).childNodes.item (5).textrntext=objRootsite.childNodes.item(StarNodes).childNodes.item (6).textrnText=replace(text,chr(32),"")rn%>rn rn 姓名: <%=username%> rn 来自:<%=fromwhere%> rn rn AllNodesNum thenrnEndNodes=EndNodes-(StarNodes-AllNodesNum)rnStarNodes=AllNodesNumrnend ifrnif EndNodes<0 thenrnEndNodes=0rnend ifrnwhile StarNodes>=EndNodesrnusername = objRootsite.childNodes.item(StarNodes).childNodes.item (1).textrnfromwhere = objRootsite.childNodes.item(StarNodes).childNodes.item (2).textrnPosttime = objRootsite.childNodes.item(StarNodes).childNodes.item (3).textrnhomepage = objRootsite.childNodes.item(StarNodes).childNodes.item (4).textrnemail=objRootsite.childNodes.item(StarNodes).childNodes.item (5).textrntext=objRootsite.childNodes.item(StarNodes).childNodes.item (6).textrnText=replace(text,chr(32),"")rn%>rn rn rn rn rn rn <%StarNodes=StarNodes-1rnWend set objXML=nothing%>rn rn 共有<< %=PageNum%>>页rn <% if cint(PageNo<>PageNum thenrnResponse.write"上一页"rnend ifrnif cint(PageNo)<>1 thenrnresponse.write"下一页"rnend ifrn%>rn rn rnrnrn 论坛

没有更多推荐了,返回首页