Skip to content

Commit efe203f

Browse files
authored
Merge pull request #22 from mischov/feature/faster-encoding
Improve FlatDom encoding performance
2 parents 3cd2979 + 78614ba commit efe203f

File tree

1 file changed

+104
-110
lines changed

1 file changed

+104
-110
lines changed

native/meeseeks_html5ever_nif/src/flat_dom.rs

Lines changed: 104 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use markup5ever::ExpandedName;
88

99
use tendril::StrTendril;
1010

11-
use rustler::types::elixir_struct::make_ex_struct;
12-
use rustler::types::map::map_new;
1311
use rustler::{Encoder, Env, Term};
1412

1513
use self::NodeEnum::{Comment, Data, Doctype, Document, Element, ProcessingInstruction, Text};
@@ -362,6 +360,15 @@ mod atoms {
362360
atom id_counter;
363361
atom roots;
364362
atom nodes;
363+
364+
atom __struct__;
365+
atom document = "Elixir.Meeseeks.Document";
366+
atom document_comment = "Elixir.Meeseeks.Document.Comment";
367+
atom document_data = "Elixir.Meeseeks.Document.Data";
368+
atom document_doctype = "Elixir.Meeseeks.Document.Doctype";
369+
atom document_element = "Elixir.Meeseeks.Document.Element";
370+
atom document_pi = "Elixir.Meeseeks.Document.ProcessingInstruction";
371+
atom document_text = "Elixir.Meeseeks.Document.Text";
365372
}
366373
}
367374

@@ -457,73 +464,67 @@ fn ns_and_tag(name: &QualName) -> (&str, &str) {
457464

458465
impl Encoder for Node {
459466
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
467+
let struct_atom = atoms::__struct__().encode(env);
460468
let parent_atom = atoms::parent().encode(env);
461469
let id_atom = atoms::id().encode(env);
462470

463471
match self.node {
464472
Comment(ref content) => {
473+
let document_comment_atom = atoms::document_comment().encode(env);
465474
let content_atom = atoms::content().encode(env);
466-
make_ex_struct(env, "Elixir.Meeseeks.Document.Comment")
467-
.ok()
468-
.unwrap()
469-
.map_put(parent_atom, self.parent.encode(env))
470-
.ok()
471-
.unwrap()
472-
.map_put(id_atom, self.id.encode(env))
473-
.ok()
474-
.unwrap()
475-
.map_put(content_atom, STW(content).encode(env))
476-
.ok()
477-
.unwrap()
475+
let keys = vec![struct_atom, parent_atom, id_atom, content_atom];
476+
let values = vec![
477+
document_comment_atom,
478+
self.parent.encode(env),
479+
self.id.encode(env),
480+
STW(content).encode(env),
481+
];
482+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
478483
}
479484

480485
Data(ref data_type, ref content) => {
486+
let document_data_atom = atoms::document_data().encode(env);
481487
let type_atom = atoms::type_().encode(env);
482488
let content_atom = atoms::content().encode(env);
483-
make_ex_struct(env, "Elixir.Meeseeks.Document.Data")
484-
.ok()
485-
.unwrap()
486-
.map_put(parent_atom, self.parent.encode(env))
487-
.ok()
488-
.unwrap()
489-
.map_put(id_atom, self.id.encode(env))
490-
.ok()
491-
.unwrap()
492-
.map_put(type_atom, data_type.encode(env))
493-
.ok()
494-
.unwrap()
495-
.map_put(content_atom, STW(content).encode(env))
496-
.ok()
497-
.unwrap()
489+
let keys = vec![struct_atom, parent_atom, id_atom, type_atom, content_atom];
490+
let values = vec![
491+
document_data_atom,
492+
self.parent.encode(env),
493+
self.id.encode(env),
494+
data_type.encode(env),
495+
STW(content).encode(env),
496+
];
497+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
498498
}
499499

500500
Doctype(ref name, ref public, ref system) => {
501+
let document_doctype_atom = atoms::document_doctype().encode(env);
501502
let name_atom = atoms::name().encode(env);
502503
let public_atom = atoms::public().encode(env);
503504
let system_atom = atoms::system().encode(env);
504-
make_ex_struct(env, "Elixir.Meeseeks.Document.Doctype")
505-
.ok()
506-
.unwrap()
507-
.map_put(parent_atom, self.parent.encode(env))
508-
.ok()
509-
.unwrap()
510-
.map_put(id_atom, self.id.encode(env))
511-
.ok()
512-
.unwrap()
513-
.map_put(name_atom, STW(name).encode(env))
514-
.ok()
515-
.unwrap()
516-
.map_put(public_atom, STW(public).encode(env))
517-
.ok()
518-
.unwrap()
519-
.map_put(system_atom, STW(system).encode(env))
520-
.ok()
521-
.unwrap()
505+
let keys = vec![
506+
struct_atom,
507+
parent_atom,
508+
id_atom,
509+
name_atom,
510+
public_atom,
511+
system_atom,
512+
];
513+
let values = vec![
514+
document_doctype_atom,
515+
self.parent.encode(env),
516+
self.id.encode(env),
517+
STW(name).encode(env),
518+
STW(public).encode(env),
519+
STW(system).encode(env),
520+
];
521+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
522522
}
523523

524524
Document => unreachable!(),
525525

526526
Element(ref name, ref attributes, ref _template) => {
527+
let document_element_atom = atoms::document_element().encode(env);
527528
let namespace_atom = atoms::namespace().encode(env);
528529
let tag_atom = atoms::tag().encode(env);
529530
let attributes_atom = atoms::attributes().encode(env);
@@ -533,63 +534,53 @@ impl Encoder for Node {
533534
.iter()
534535
.map(|a| (QNW(&a.name), STW(&a.value)).encode(env))
535536
.collect();
536-
make_ex_struct(env, "Elixir.Meeseeks.Document.Element")
537-
.ok()
538-
.unwrap()
539-
.map_put(parent_atom, self.parent.encode(env))
540-
.ok()
541-
.unwrap()
542-
.map_put(id_atom, self.id.encode(env))
543-
.ok()
544-
.unwrap()
545-
.map_put(namespace_atom, namespace.encode(env))
546-
.ok()
547-
.unwrap()
548-
.map_put(tag_atom, tag.encode(env))
549-
.ok()
550-
.unwrap()
551-
.map_put(attributes_atom, attribute_terms.encode(env))
552-
.ok()
553-
.unwrap()
554-
.map_put(children_atom, self.children.encode(env))
555-
.ok()
556-
.unwrap()
537+
let keys = vec![
538+
struct_atom,
539+
parent_atom,
540+
id_atom,
541+
namespace_atom,
542+
tag_atom,
543+
attributes_atom,
544+
children_atom,
545+
];
546+
let values = vec![
547+
document_element_atom,
548+
self.parent.encode(env),
549+
self.id.encode(env),
550+
namespace.encode(env),
551+
tag.encode(env),
552+
attribute_terms.encode(env),
553+
self.children.encode(env),
554+
];
555+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
557556
}
558557

559558
ProcessingInstruction(ref target, ref data) => {
559+
let document_pi_atom = atoms::document_pi().encode(env);
560560
let target_atom = atoms::target().encode(env);
561561
let data_atom = atoms::data().encode(env);
562-
make_ex_struct(env, "Elixir.Meeseeks.Document.ProcessingInstruction")
563-
.ok()
564-
.unwrap()
565-
.map_put(parent_atom, self.parent.encode(env))
566-
.ok()
567-
.unwrap()
568-
.map_put(id_atom, self.id.encode(env))
569-
.ok()
570-
.unwrap()
571-
.map_put(target_atom, STW(target).encode(env))
572-
.ok()
573-
.unwrap()
574-
.map_put(data_atom, STW(data).encode(env))
575-
.ok()
576-
.unwrap()
562+
let keys = vec![struct_atom, parent_atom, id_atom, target_atom, data_atom];
563+
let values = vec![
564+
document_pi_atom,
565+
self.parent.encode(env),
566+
self.id.encode(env),
567+
STW(target).encode(env),
568+
STW(data).encode(env),
569+
];
570+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
577571
}
578572

579573
Text(ref content) => {
574+
let document_text_atom = atoms::document_text().encode(env);
580575
let content_atom = atoms::content().encode(env);
581-
make_ex_struct(env, "Elixir.Meeseeks.Document.Text")
582-
.ok()
583-
.unwrap()
584-
.map_put(parent_atom, self.parent.encode(env))
585-
.ok()
586-
.unwrap()
587-
.map_put(id_atom, self.id.encode(env))
588-
.ok()
589-
.unwrap()
590-
.map_put(content_atom, STW(content).encode(env))
591-
.ok()
592-
.unwrap()
576+
let keys = vec![struct_atom, parent_atom, id_atom, content_atom];
577+
let values = vec![
578+
document_text_atom,
579+
self.parent.encode(env),
580+
self.id.encode(env),
581+
STW(content).encode(env),
582+
];
583+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
593584
}
594585
}
595586
}
@@ -599,26 +590,29 @@ impl Encoder for Node {
599590

600591
impl Encoder for FlatDom {
601592
fn encode<'a>(&self, env: Env<'a>) -> Term<'a> {
593+
let struct_atom = atoms::__struct__().encode(env);
594+
let document_atom = atoms::document().encode(env);
602595
let id_counter_atom = atoms::id_counter().encode(env);
603596
let roots_atom = atoms::roots().encode(env);
604597
let nodes_atom = atoms::nodes().encode(env);
605598
let id_counter = self.nodes.len() - 1;
606599
let roots = &self.nodes[0].children;
607-
let nodes = map_new(env);
608-
let nodes_term = self.nodes.iter().skip(1).fold(nodes, |m, n| {
609-
m.map_put(n.id.encode(env), n.encode(env)).ok().unwrap()
610-
});
611-
make_ex_struct(env, "Elixir.Meeseeks.Document")
612-
.ok()
613-
.unwrap()
614-
.map_put(id_counter_atom, id_counter.encode(env))
615-
.ok()
616-
.unwrap()
617-
.map_put(roots_atom, roots.encode(env))
618-
.ok()
619-
.unwrap()
620-
.map_put(nodes_atom, nodes_term)
600+
let (node_keys, node_values): (Vec<_>, Vec<_>) = self
601+
.nodes
602+
.iter()
603+
.skip(1)
604+
.map(|n| (n.id.encode(env), n.encode(env)))
605+
.unzip();
606+
let nodes_term = Term::map_from_arrays(env, &node_keys, &node_values)
621607
.ok()
622-
.unwrap()
608+
.unwrap();
609+
let keys = vec![struct_atom, id_counter_atom, roots_atom, nodes_atom];
610+
let values = vec![
611+
document_atom,
612+
id_counter.encode(env),
613+
roots.encode(env),
614+
nodes_term,
615+
];
616+
Term::map_from_arrays(env, &keys, &values).ok().unwrap()
623617
}
624618
}

0 commit comments

Comments
 (0)