上一篇 用 HexColor 作为示例,可能过于简单

这里再补充一个 ini 解析的示例

由于实在写不动用其他库解析 ini 了, 春节都要过完了,累了,写不动了,

所以随意找了一份解析ini的库, 仅供参考,对比不准确,毕竟完整库包含了更多功能

先看看结果


BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3085/23H2/2023Update/SunValley3)
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK 8.0.200
[Host] : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX2
Method Mean Error StdDev Gen0 Gen1 Allocated
Hande_Ini 567.9 ns 11.24 ns 21.66 ns 0.2851 - 1.75 KB
RuQu_Ini 1,691.4 ns 33.48 ns 64.51 ns 0.4177 - 2.56 KB
IniDataParser 4,836.3 ns 94.44 ns 167.87 ns 1.1215 0.0076 6.91 KB
// * Legends *
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Gen0 : GC Generation 0 collects per 1000 operations
Gen1 : GC Generation 1 collects per 1000 operations
Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B)
1 ns : 1 Nanosecond (0.000000001 sec)

总结

  • delegate 肯定会有调用消耗,ini 场景使用的函数远多于 HexColor ,可以看到消耗大了很多

先看来自 dotnet Microsoft.Extensions.Configuration 中解析 ini 的代码

public static IDictionary<string, string?> Read(string content)
{
var data = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
using (var reader = new StringReader(content))
{
string sectionPrefix = string.Empty; while (reader.Peek() != -1)
{
string rawLine = reader.ReadLine()!; // Since Peak didn't return -1, stream hasn't ended.
string line = rawLine.Trim(); // Ignore blank lines
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
// Ignore comments
if (line[0] is ';' or '#' or '/')
{
continue;
}
// [Section:header]
if (line[0] == '[' && line[line.Length - 1] == ']')
{
// remove the brackets
sectionPrefix = string.Concat(line.AsSpan(1, line.Length - 2).Trim(), ConfigurationPath.KeyDelimiter);
continue;
} // key = value OR "value"
int separator = line.IndexOf('=');
if (separator < 0)
{
throw new FormatException(rawLine);
} string key = sectionPrefix + line.Substring(0, separator).Trim();
string value = line.Substring(separator + 1).Trim(); // Remove quotes
if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"')
{
value = value.Substring(1, value.Length - 2);
} if (data.ContainsKey(key))
{
throw new FormatException(key);
} data[key] = value;
}
}
return data;
}

再来看看部分函数语义优化的代码

public class Ini
{
private static Ini instance = new Ini(); public Func<IPeeker<char>, bool> WhiteSpace = Chars.IngoreWhiteSpace.Map(i => i > 0); public Func<IPeeker<char>, bool> Comment = Chars.In(";#/").Delimited(Chars.NotCRLF.ToSlice().Opt(), Chars.IsCRLF, "Comment not right").Map((c, x, y, z) => c); public Func<IPeeker<char>, string> SectionName = Chars.Is('[').Delimited(Chars.Not(']').ToSlice().Once("Section name is required."), Chars.Is(']'), "Section name must end with ']'").Map((c, x, y, z) => y?.ToString()); public Func<IPeeker<char>, string> Key = Chars.Not('=').ToSlice().Once("key is required.").Map(i => i.ToString());
public Func<IPeeker<char>, char> Separater = Chars.Is('=').Once("Section name is required."); public Func<IPeeker<char>, string> Value = Chars.NotCRLF.ToSlice().Once("value is required.").Map(i =>
{
var v = i.ToString().Trim();
return v.StartsWith('"') ? v[1..^1] : v;
}); public IDictionary<string, string> ParseString(string content)
{
var input = Input.From(content);
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
while (input.TryPeek(out var v))
{
if (!(WhiteSpace(input) || Comment(input) || Section(input, dict)))
{
throw new NotSupportedException(v.ToString());
}
}
return dict;
} public bool SectionContentEnd(IPeeker<char> input)
{
return !input.TryPeek(out var v) || v is '[';
} public bool Section(StringPeeker input, Dictionary<string, string> dict)
{
var name = SectionName(input);
if (name == null) return false;
while (!SectionContentEnd(input))
{
if (WhiteSpace(input) || Comment(input))
{
continue;
}
SectionKV(input, dict, name);
}
return true;
} public void SectionKV(StringPeeker input, Dictionary<string, string> dict, string name)
{
var k = Key(input);
Separater(input);
var v = Value(input);
k = $"{name}:{k.Trim()}";
dict.Add(k, v.Trim());
} public static IDictionary<string, string> Parse(string content)
{
return instance.ParseString(content);
}
}

最后截取 部分 ini 解析库的代码 仅供参考

public IniData Parse(string iniDataString)
{
IniData iniData = (Configuration.CaseInsensitive ? new IniDataCaseInsensitive() : new IniData());
iniData.Configuration = Configuration.Clone();
if (string.IsNullOrEmpty(iniDataString))
{
return iniData;
} _errorExceptions.Clear();
_currentCommentListTemp.Clear();
_currentSectionNameTemp = null;
try
{
string[] array = iniDataString.Split(new string[2] { "\n", "\r\n" }, StringSplitOptions.None);
for (int i = 0; i < array.Length; i++)
{
string text = array[i];
if (text.Trim() == string.Empty)
{
continue;
} try
{
ProcessLine(text, iniData);
}
catch (Exception ex)
{
ParsingException ex2 = new ParsingException(ex.Message, i + 1, text, ex);
if (Configuration.ThrowExceptionsOnError)
{
throw ex2;
} _errorExceptions.Add(ex2);
}
} if (_currentCommentListTemp.Count > 0)
{
if (iniData.Sections.Count > 0)
{
iniData.Sections.GetSectionData(_currentSectionNameTemp).TrailingComments.AddRange(_currentCommentListTemp);
}
else if (iniData.Global.Count > 0)
{
iniData.Global.GetLast().Comments.AddRange(_currentCommentListTemp);
} _currentCommentListTemp.Clear();
}
}
catch (Exception item)
{
_errorExceptions.Add(item);
if (Configuration.ThrowExceptionsOnError)
{
throw;
}
} if (HasError)
{
return null;
} return (IniData)iniData.Clone();
}

完整代码参考 https://github.com/fs7744/ruqu

通过解析库探究函数式抽象代价 ( ini 解析示例补充)的更多相关文章

  1. 爬虫(五)—— 解析库(二)beautiful soup解析库

    目录 解析库--beautiful soup 一.BeautifulSoup简介 二.安装模块 三.Beautiful Soup的基本使用 四.Beautiful Soup查找元素 1.查找文本.属性 ...

  2. 【开源】libinimini:适用于单片机的极简 ini 解析库

    介绍说明 最近自己基于 XR872 在做一个小作品练习练习,具备可以配置的功能,选择了使用 ini 作为配置文件.我调研了网上常见的 ini 解析库,几乎都涉及到了 fopen()/fgets().. ...

  3. OpenStack配置解析库oslo.config的使用方法

    OpenStack的oslo项目旨在独立出系统中可重用的基础功能,oslo.config就是其中一个被广泛使用的库,该项工作的主要目的就是解析OpenStack中命令行(CLI)或配置文件(.conf ...

  4. C++的Json解析库:jsoncpp和boost(转)

    原文转自 http://blog.csdn.net/hzyong_c/article/details/7163589 JSON(JavaScript Object Notation)跟xml一样也是一 ...

  5. [转]C++的Json解析库:jsoncpp和boost

    JSON(JavaScript Object Notation)跟xml一样也是一种数据交换格式,了解json请参考其官网http://json.org,本文不再对json做介绍,将重点介绍c++的j ...

  6. golang常用库:配置文件解析库-viper使用

    一.viper简介 viper 配置解析库,是由大神 Steve Francia 开发,他在google领导着 golang 的产品开发,他也是 gohugo.io 的创始人之一,命令行解析库 cob ...

  7. Boost.JSON Boost的JSON解析库(1.75首发)

    目录 目录 Boost的1.75版本新库 JSON库简介 JSON的简单使用 编码 最通用的方法 使用std::initializer_list json对象的输出 两种对比 解码 简单的解码 增加错 ...

  8. 解析库beautifulsoup

    目录 一.介绍 二.遍历文档树 三.搜索文档树(过滤) 四.修改文档树 五.总结 一.介绍 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的 ...

  9. Pugixml一种快速解析XML文件的开源解析库

    Pugixml是一个轻量级的C++ XML开源解析库,DOM形式的解析器.接口和丰富的遍历和修改操作,快速的解析,此外支持XPath1.0实现数据查询,支持unicode编码: 使用Pugixml可通 ...

  10. Tomjson - 一个"短小精悍"的 json 解析库

    Tomjson,一个"短小精悍"的 json 解析库,tomjson使用Java语言编写,主要作用是把Java对象(JavaBean)序列化为json格式字符串,将json格式字符 ...

随机推荐

  1. freeswitch的3XX重定向

    概述 sip协议标准RFC3261中,对3XX重定向有明确的定义. freeswitch中如何使用3XX redirect的特性,如何落地,应用场景有哪些? 环境 centos:CentOS  rel ...

  2. python测试小工具

    2022年第三天,祝福大家元旦快乐,此测试工具在原基础上改进,增加一些新的功能,并去除了复杂的层级链接,架构目前比较简单,全部只使用了一个GridBagSizer布局器完成. 一.背景:主要解决软件测 ...

  3. python · SQL | MySQL 配置与 python 连接数据库

    来存档一下搞 sql 的过程,方便以后查阅. 安装与配置 mysql server:https://blog.csdn.net/zhende_lan/article/details/129318514 ...

  4. 到底什么样的 Java 项目用 Solon 好???

    什么样的 Java 项目用 Solon 好 就像华为讲的,不要因为爱国而特意买华为手机.Solon 也是,有需要就用不需要就跳过(按正常的需求选择): 信创需要国产化,应该用 Solon 或者 Sol ...

  5. Verilog Review

    Agenda 目的 Verilog概述 Verilog建模 模块 模块组成 书写建议 时延 Verilog基本语法 标识符 可读性 注释 空格 数据类型 操作数 运算符 条件语句 循环语句 函数 Ve ...

  6. 【MicroPython】生成QSTR表 - py\makeqstrdata.py

    转义非字母数字的字符,转义结果为预定义字符串codepoint2name[] def qstr_escape(qst): def esc_char(m): c = ord(m.group(0)) tr ...

  7. Go-值传递&引用传递

    值类型和引用类型 值类型关注其值 引用类型关注其指针 值类型和引用类型区别在于传递值的时候拷贝的对象不同,值传递拷贝是变量的值,引用传递拷贝的是变量的指针 拷贝 -- 传递值 赋值 函数调用 初始化 ...

  8. 阿里云ECS自建K8S_IPV6重启后异常问题解决过程

    阿里云ECS自建K8S_IPV6重启后异常问题解决过程 背景 最近安装了一个单节点的K8S_IPV6 昨天不知道何故 突然宕机了. 然后只能在阿里云的控制台后台重启了ECS 启动之后看K8S的状态一开 ...

  9. [转帖]tidb-lightning 逻辑模式导入

    https://docs.pingcap.com/zh/tidb/stable/tidb-lightning-configuration 本文档介绍如何编写逻辑导入模式的配置文件,如何进行性能调优等内 ...

  10. 物理机和虚拟机上CPU睿频的区别

    物理机和虚拟机上CPU睿频的区别 关于睿频 睿频是指当启动一个运行程序后,处理器会自动加速到合适的频率, 而原来的运行速度会提升 10%~20% 以保证程序流畅运行的一种技术. 一般max的睿频不能超 ...