From 66ac52c5dba12224f65fc4dd4568ff49e959696c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Geoffrey=20=E2=80=9CFrogeye=E2=80=9D=20Preud=27homme?= Date: Mon, 9 Dec 2019 10:42:37 +0100 Subject: [PATCH] Workflow: JSON parser acceleration Sadly is even worse because of the ctypes-induced conversions. --- accel.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++- feed_dns.py | 33 +++++++++++++++++---------- 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/accel.c b/accel.c index bda0072..72acc32 100644 --- a/accel.c +++ b/accel.c @@ -1,6 +1,7 @@ #include +#include -int ip4_flat(char* value, wchar_t* flat) +char ip4_flat(char* value, wchar_t* flat) { unsigned char value_index = 0; unsigned char octet_index = 0; @@ -35,3 +36,66 @@ int ip4_flat(char* value, wchar_t* flat) } while (1); // This ugly thing save one comparison return 1; } + +#define MAX_OUTPUT 255 + +char feed_dns_parse_json(char* line, char* name, char* value) +{ + unsigned short line_index = 0; + unsigned char quote_index = 0; + unsigned char output_index = 0; + char line_chara; + char* current_output = NULL; + char type = 0; // 0: error, 1: cname, 2: a, 3: aaaa + do { + line_chara = line[line_index]; + if (line_chara == '"') { + quote_index += 1; + switch (quote_index) { + case 7: // Start of name + current_output = name; + break; + case 8: // End of name + name[output_index] = '\0'; + current_output = NULL; + break; + case 11: // Start of type + line_chara = line[++line_index]; + if (line_chara == 'c') { // Must be CNAME + type = 1; + break; + } else if (line_chara == 'a') { // A or AAAA + line_chara = line[++line_index]; + if (line[line_chara+2] == '"') { // Is A + type = 2; + quote_index++; + break; + } else if (line[line_chara+1] == 'a') { // Must be AAAA + type = 3; + break; + } + } + return 0; + case 15: // Start of value + current_output = value; + break; + case 16: // End of value + value[output_index] = '\0'; + return type; + } + output_index = 0; + } else if (line_chara == '\0') { + return 0; + } else { + if (current_output != 0) { + if (output_index >= MAX_OUTPUT) { + return 0; + } + current_output[output_index] = line_chara; + output_index++; + } + } + line_index++; + } while (1); // This ugly thing save one comparison + return 0; +} diff --git a/feed_dns.py b/feed_dns.py index 1cc3247..0505155 100755 --- a/feed_dns.py +++ b/feed_dns.py @@ -3,10 +3,16 @@ import database import argparse import sys +import ctypes +import json + +ACCEL = ctypes.cdll.LoadLibrary('./libaccel.so') +ACCEL_NAME_BUF = ctypes.create_string_buffer(b'Z'*255, 255) +ACCEL_VALUE_BUF = ctypes.create_string_buffer(b'Z'*255, 255) FUNCTION_MAP = { - b'a': database.feed_a, - b'cname': database.feed_cname, + b'a': database.feed_a, + b'cname': database.feed_cname, } if __name__ == '__main__': @@ -21,21 +27,24 @@ if __name__ == '__main__': database.open_db() + line = b'(none)' + + def err(name: bytes, value: bytes) -> None: + print(f"Error with line: {line!r}") + + FUNCTIONS = [err, database.feed_cname, database.feed_a] + try: database.time_step('iowait') - line: bytes for line in args.input: database.time_step('feed_json_parse') - split = line.split(b'"') - name = split[7] - dtype = split[11] - value = split[15] - # data = json.loads(line) - # assert dtype == data['type'] - # assert name == data['name'] - # assert value == data['value'] + dtype = ACCEL.feed_dns_parse_json( + ctypes.c_char_p(line), + ACCEL_NAME_BUF, + ACCEL_VALUE_BUF + ) database.time_step('feed_switch') - FUNCTION_MAP[dtype](name, value) + FUNCTIONS[dtype](ACCEL_NAME_BUF.value, ACCEL_VALUE_BUF.value) database.time_step('iowait') except KeyboardInterrupt: print("Interupted.")