- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个 JSON 文件(只是一个字典数组),大小为 60 兆字节。在 PHP 中解析需要 2 秒,但在 Swift 中它有七秒长。这是荒唐的。是我做错了什么还是什么?快速代码:
let json = try! JSONSerialization.jsonObject(
with: try! Data(
contentsOf: URL(
fileURLWithPath: "/some/file/path/to.json"
)
)
) as! [[AnyHashable: Any]]
我简化了代码,所以它是一个操作,但慢的部分是 JSONSerialization.jsonObject,我明确地测量了它(从文件加载数据的速度如预期的那样快)。 PHP 代码非常简单 - json_decode(file_get_contents())
。
值得一提的是,在 Release模式下构建(通过优化)并没有改善这种情况。
UPD:分析应用程序后,我发现瓶颈是将结果转换为 [[AnyHashable: Any]],将其更改为 [[String: Any]] 稍微改善了情况(从 7 秒到 ~ 5.3),但仍然是耻辱和痛苦。
现在的问题基本上是:为什么转换这么慢,有没有一种方法可以更快地处理大型 JSON 对象(或任何其他序列化数据)?
最佳答案
关于用 JSON 编码 60MB,我不会评判你……好吧,我要评判你一点。这是一种存储这么多数据的疯狂格式。从我的系统中得到它;让我们努力让它变得更快。
首先,你能直接跳到 Swift 4 吗?如果是这样,摆脱 JSONSerialization
并直接进入新的 JSONDecoder
.它避免了很多类型问题。也就是说,它可能会或可能不会更快。
让我们回到“为什么转换这么慢”的问题。简单的。类型转换速度很快。你没有施法。你正在转换。 AnyHashable
是一个类型删除器;它是与 String
完全不同的结构类型:
public struct AnyHashable {
您必须将 String
装箱到 AnyHashable
结构中。这实际上非常快(因为写时复制的工作方式),但这意味着字典是一个完全不同的字典。你强制它制作完整的副本。
我过去处理大量 JSON 数组的方式是手动部分解析它们。扔掉第一个 [
,一次收集一个 JSON 对象,解析它,然后把结果放到一个数组中。这样您就不必将所有数据都拉入内存,也不需要刻录 600MB 的高水位标记。如果您对输入 JSON 有一定的控制权,这种技术显然最有效。例如,我通常会作弊并像这样编写 JSON:
[
{ ... JSON ... },
{ ... JSON ... }
]
这使得解析记录变得非常快速和容易(只需按换行符拆分)。 (我碰巧也喜欢这个,因为它对像 grep 和 awk 这样的命令行工具很友好,根本没有 JSON 解析)。它仍然是合法的 JSON,但通过一些特殊知识我可以更快地解析它。
对于基准测试,我还建议您在 ObjC 中构建它以将 NSJSONSerialization
与“将 ObjC 类型桥接至 Swift”分开。 NSJSONSerialization
通常被认为是一个非常快速的解析器。如果您不是很小心(如上所述),那么桥接到 Swift 会很昂贵。 (我喜欢 Swift,但它是一种很难推理性能的语言。)
看起来这个空间里还有另一个玩家叫JASON
,但我还没有尝试过。 (曾经有一个非常有名的包,叫做 JSONKit
,它通过玩 ObjC 技巧来疯狂地快,这会让你的皮肤起鸡皮疙瘩,但惊人地工作得非常好,所以必须原谅。但这些技巧终于 catch 了它,而且我认为它甚至不再起作用了。)
关于swift - Swift 中的 JSONSerialization.jsonObject 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45102094/
问题 我有一个 Spring MVC 应用程序,它要求我将某个实体列表的 id 和名称转换为具有特定格式的 JSON 对象数组,并在某个请求上输出。也就是说,我需要一个像这样的 JSON 对象数组:
当我阅读最新 RestSharp 的 readme.txt 时: *** IMPORTANT CHANGE IN RESTSHARP VERSION 103 *** In 103.0, JSON.NE
我有两个类(class)。以二等领域第一。 class A { @JsonSerializer(using = CustomBSerializer.class) private B b; }
有什么方法可以从 JsonSerializer 类中取出设置并在新的 JsonSerializer 中重新实现它们? 似乎没有任何方法可以做那样的事情。我发现最好的是通过反射调用的私有(private
在我的java应用程序中,我分别使用 JsonSerializer 和 JsonSerializer() 来序列化 java.util.Date 和 java.sql.Timestamp 字段。但问题
我想使用 Foundation 的 JSONSerialization.data(withJSONObject obj: AnyObject, options opt:writingOptions =
根据PHP手册 If a Pure Enum is serialized to JSON, an error will be thrown. If a Backed Enum is serialize
我有一个父类,我在其上指定了一个像这样的自定义反序列化器 - @JsonDeserialize(using = CustomDeserializer.class) public class Paren
根据PHP手册 If a Pure Enum is serialized to JSON, an error will be thrown. If a Backed Enum is serialize
我有一个位于 .jar 中的类,但无法修改。 它在类上有一个 @JsonSerialize() 注释。 @JsonSerialize(using = SomeClassSerializer.class
我正在使用 JSON token 开发 iOS,但遇到了 unsupported_grant_type 错误。我正在开发的代码如下 let params = ["grant_type": "passw
我有以下代码将 joda 的 LocalDate 序列化为字符串: public class JodaDateSerializer extends JsonSerializer { priva
我想添加一个包装器,其命名是在运行时确定的,因为它取决于类名(我可以使用@JsonRootName,但我不想这样做,因为我必须在每个子类上使用它,即效率不高)。 我想我应该使用 @JsonSerial
我编写了一个自定义的 JsonSerializer 来将 BigDecimal 转换为 String。我想使用 @JsonSerialize 注释调用此序列化程序,但有条件地,即如果特定 boolea
JSONSerialization 未在服务器发送时序列化数据。它反转数据。我使用后端的数据过滤 API。它发送准确的数据,我还检查了 postman 和 Android 端,但 iOS 代码更改了响
我正在尝试将 SwiftyJSON 与我的 JSON api 数据一起使用,但我无法理解转换的工作原理。 这是 SwiftyJSON Git 的链接:https://github.com/Swifty
我有一个自定义类 public class Balance: NSObject { var details: String var date: Date var amount:
我在解析 json 时遇到错误 "hoursOfOperation" : { "sat" : { "enabled" : true, "schedule"
什么是 option: [] in JSONSerialization in swift let jsonData = try JSONSerialization.data(withJSONObjec
我在将我的模型翻译成字典时遇到了问题。我的模型继承自 Codable,当使用 JSONSerialization 时,我得到了一个字典,其形式为: (...,"sensors": ( { accx =
我是一名优秀的程序员,十分优秀!