How to get query timing in Tarantool like in other DBMS - query-optimization

In MySQL/PostgreSQL/Oracle/MSSQL there's always duration in every query executed "Query completed in 0.23ms" or "Elapsed 0.001s" or at least when "EXPLAIN" or "EXPLAIN ANALYZE" the timings are shown. How to do this in tarantool client? (tarantoolctl connect 3301)
For example with EXPLAIN QUERY PLAN doesn't show the timing at all:
box.execute "explain query plan \nWITH sc AS ( -- shown count\n\tSELECT \"ref_id\"\n\t\t, \"view_count\"\n\tFROM \"userlistings\"\n\tWHERE \"user_id\" = 'af07e444-44f3-4116-833e-90af7f24ffa0'\n), msc AS (\n\tSELECT GREATEST(1,MAX(\"view_count\")) \"max_view\"\n\tFROM sc\n)\n, \nopq AS ( \n\tSELECT \"cat_id\"\n\t\t, \"click_interest\" -- SPEC-Q\n\t\t, \"purchase_interest\" -- SPEC-P\n\t\t, \"message_interest\" -- SPEC-O\n\tFROM \"usercats\"\n\tWHERE \"user_id\" = 'af07e444-44f3-4116-833e-90af7f24ffa0'\n), mopq AS (\n\tSELECT GREATEST(1,MAX(\"click_interest\")) \"max_click\"\n\t\t, GREATEST(1,MAX(\"purchase_interest\")) \"max_purchase\"\n\t\t, GREATEST(1,MAX(\"message_interest\")) \"max_inquiry\"\n\tFROM opq\n)\nSELECT \"initial_cache\" \n+ (IFNULL(msc.\"max_view\",1) - IFNULL(sc.\"view_count\",0)) / IFNULL(msc.\"max_view\",1) * 100.0 * 5.28000020980835/100.010002136\n+ ((180-abs(\"lat\" - -5.796658992767334))/360.0 + (360-abs(\"long\" - 106.49927520751953))/720.0) * 100.0 * 22.280000686645508/100.010002136\n+ IFNULL(\"message_interest\",0) / IFNULL(mopq.\"max_inquiry\",1) * 100.0 * 0/100.010002136\n+ IFNULL(\"purchase_interest\",0) / IFNULL(mopq.\"max_purchase\",1) * 100.0 * 5.28000020980835/100.010002136\n+ IFNULL(\"click_interest\",0) / IFNULL(mopq.\"max_click\",1) * 100.0 * 0/100.010002136, *\nFROM \"listings\"\n\nLEFT JOIN sc\n\tON \"listings\".\"ref_id\" = sc.\"ref_id\"\nCROSS JOIN msc\n\nLEFT JOIN opq\n\tON \"listings\".\"categories\" = opq.\"cat_id\"\nCROSS JOIN mopq\n\nWHERE \"ref_type\" = 1\nORDER BY 1 DESC LIMIT 5 OFFSET 0"
---
- metadata:
- name: selectid
type: integer
- name: order
type: integer
- name: from
type: integer
- name: detail
type: text
rows:
- [1, 0, 0, 'SEARCH TABLE userlistings USING PRIMARY KEY (user_id=?) (~10 rows)']
- [2, 0, 0, 'SEARCH TABLE userlistings USING PRIMARY KEY (user_id=?) (~10 rows)']
- [3, 0, 0, 'SEARCH TABLE usercats USING PRIMARY KEY (user_id=?) (~10 rows)']
- [4, 0, 0, 'SEARCH TABLE usercats USING PRIMARY KEY (user_id=?) (~10 rows)']
- [0, 0, 0, 'SEARCH TABLE listings USING COVERING INDEX ref_type (ref_type=?) (~10
rows)']
- [0, 1, 1, 'SCAN SUBQUERY 1 (~1 row)']
- [0, 2, 2, 'SCAN SUBQUERY 2 (~1 row)']
- [0, 3, 3, 'SCAN SUBQUERY 3 (~1 row)']
- [0, 4, 4, 'SCAN SUBQUERY 4 (~1 row)']
- [0, 0, 0, 'USE TEMP B-TREE FOR ORDER BY']
...
or in EXPLAIN also doesn't show any timing/duration:
box.execute "explain \nWITH sc AS ( -- shown count\n\tSELECT \"ref_id\"\n\t\t, \"view_count\"\n\tFROM \"userlistings\"\n\tWHERE \"user_id\" = 'af07e444-44f3-4116-833e-90af7f24ffa0'\n), msc AS (\n\tSELECT GREATEST(1,MAX(\"view_count\")) \"max_view\"\n\tFROM sc\n)\n, \nopq AS ( \n\tSELECT \"cat_id\"\n\t\t, \"click_interest\" -- SPEC-Q\n\t\t, \"purchase_interest\" -- SPEC-P\n\t\t, \"message_interest\" -- SPEC-O\n\tFROM \"usercats\"\n\tWHERE \"user_id\" = 'af07e444-44f3-4116-833e-90af7f24ffa0'\n), mopq AS (\n\tSELECT GREATEST(1,MAX(\"click_interest\")) \"max_click\"\n\t\t, GREATEST(1,MAX(\"purchase_interest\")) \"max_purchase\"\n\t\t, GREATEST(1,MAX(\"message_interest\")) \"max_inquiry\"\n\tFROM opq\n)\nSELECT \"initial_cache\" \n+ (IFNULL(msc.\"max_view\",1) - IFNULL(sc.\"view_count\",0)) / IFNULL(msc.\"max_view\",1) * 100.0 * 5.28000020980835/100.010002136\n+ ((180-abs(\"lat\" - -5.796658992767334))/360.0 + (360-abs(\"long\" - 106.49927520751953))/720.0) * 100.0 * 22.280000686645508/100.010002136\n+ IFNULL(\"message_interest\",0) / IFNULL(mopq.\"max_inquiry\",1) * 100.0 * 0/100.010002136\n+ IFNULL(\"purchase_interest\",0) / IFNULL(mopq.\"max_purchase\",1) * 100.0 * 5.28000020980835/100.010002136\n+ IFNULL(\"click_interest\",0) / IFNULL(mopq.\"max_click\",1) * 100.0 * 0/100.010002136, *\nFROM \"listings\"\n\nLEFT JOIN sc\n\tON \"listings\".\"ref_id\" = sc.\"ref_id\"\nCROSS JOIN msc\n\nLEFT JOIN opq\n\tON \"listings\".\"categories\" = opq.\"cat_id\"\nCROSS JOIN mopq\n\nWHERE \"ref_type\" = 1\nORDER BY 1 DESC LIMIT 5 OFFSET 0"
---
- metadata:
- name: addr
type: integer
- name: opcode
type: text
- name: p1
type: integer
- name: p2
type: integer
- name: p3
type: integer
- name: p4
type: text
- name: p5
type: text
- name: comment
type: text
rows:
- [0, 'Init', 0, 324, 0, '', '00', null]
- [1, 'Integer', 18, 1, 0, '', '00', null]
- [2, 'Once', 0, 18, 0, '', '00', null]
- [3, 'OpenTEphemeral', 2, 3, 0, 'k(2,B,B)', '00', null]
- [4, 'IteratorOpen', 1, 0, 2, '', '00', null]
- [5, 'IteratorOpen', 11, 0, 0, 'space<name=userlistings>', '02', null]
- [6, 'String8', 0, 3, 0, 'af07e444-44f3-4116-833e-90af7f24ffa0', '00', null]
- [7, 'ApplyType', 3, 1, 0, "\x02", '00', null]
- [8, 'SeekGE', 11, 18, 3, '1', '00', null]
- [9, 'IdxGT', 11, 18, 3, '1', '00', null]
- [10, 'Column', 11, 1, 4, '', '00', null]
- [11, 'Column', 11, 2, 5, '', '00', null]
- [12, 'MakeRecord', 4, 2, 6, '', '01', null]
- [13, 'NextIdEphemeral', 2, 10, 0, '', '00', null]
- [14, 'Copy', 4, 8, 1, '', '00', null]
- [15, 'MakeRecord', 8, 3, 7, '', '01', null]
- [16, 'IdxInsert', 7, 2, 0, '', '00', null]
- [17, 'Next', 11, 9, 0, '', '00', null]
- [18, 'Return', 1, 0, 0, '', '00', null]
- [19, 'Integer', 42, 11, 0, '', '00', null]
- [20, 'Once', 0, 42, 0, '', '00', null]
- [21, 'OpenTEphemeral', 12, 2, 0, 'k(1,B)', '00', null]
- [22, 'IteratorOpen', 2, 0, 12, '', '00', null]
- [23, 'Null', 0, 13, 14, '', '00', null]
- [24, 'IteratorOpen', 12, 0, 0, 'space<name=userlistings>', '02', null]
- [25, 'String8', 0, 15, 0, 'af07e444-44f3-4116-833e-90af7f24ffa0', '00', null]
- [26, 'ApplyType', 15, 1, 0, "\x02", '00', null]
- [27, 'SeekGE', 12, 33, 15, '1', '00', null]
- [28, 'IdxGT', 12, 33, 15, '1', '00', null]
- [29, 'Column', 12, 2, 16, '', '00', null]
- [30, 'CollSeq', 0, 0, 0, '(binary)', '00', null]
- [31, 'AggStep0', 0, 16, 13, 'MAX(1)', '01', null]
- [32, 'Next', 12, 28, 0, '', '00', null]
- [33, 'AggFinal', 13, 1, 0, 'MAX(1)', '00', null]
- [34, 'Copy', 13, 19, 0, '', '00', null]
- [35, 'CollSeq', 0, 0, 0, '({type = binary})', '00', null]
- [36, 'BuiltinFunction0', 1, 18, 17, 'GREATEST(-1)', '02', null]
- [37, 'MakeRecord', 17, 1, 16, '', '01', null]
- [38, 'NextIdEphemeral', 12, 22, 0, '', '00', null]
- [39, 'Copy', 17, 21, 0, '', '00', null]
- [40, 'MakeRecord', 21, 2, 20, '', '01', null]
- [41, 'IdxInsert', 20, 12, 0, '', '00', null]
- [42, 'Return', 11, 0, 0, '', '00', null]
- [43, 'Integer', 62, 23, 0, '', '00', null]
- [44, 'Once', 0, 62, 0, '', '00', null]
- [45, 'OpenTEphemeral', 24, 5, 0, 'k(4,B,B,B,B)', '00', null]
- [46, 'IteratorOpen', 3, 0, 24, '', '00', null]
- [47, 'IteratorOpen', 13, 0, 0, 'space<name=usercats>', '02', null]
- [48, 'String8', 0, 25, 0, 'af07e444-44f3-4116-833e-90af7f24ffa0', '00', null]
- [49, 'ApplyType', 25, 1, 0, "\x02", '00', null]
- [50, 'SeekGE', 13, 62, 25, '1', '00', null]
- [51, 'IdxGT', 13, 62, 25, '1', '00', null]
- [52, 'Column', 13, 1, 26, '', '00', null]
- [53, 'Column', 13, 5, 27, '', '00', null]
- [54, 'Column', 13, 4, 28, '', '00', null]
- [55, 'Column', 13, 3, 29, '', '00', null]
- [56, 'MakeRecord', 26, 4, 30, '', '01', null]
- [57, 'NextIdEphemeral', 24, 36, 0, '', '00', null]
- [58, 'Copy', 26, 32, 3, '', '00', null]
- [59, 'MakeRecord', 32, 5, 31, '', '01', null]
- [60, 'IdxInsert', 31, 24, 0, '', '00', null]
- [61, 'Next', 13, 51, 0, '', '00', null]
- [62, 'Return', 23, 0, 0, '', '00', null]
- [63, 'Integer', 100, 37, 0, '', '00', null]
- [64, 'Once', 0, 100, 0, '', '00', null]
- [65, 'OpenTEphemeral', 38, 4, 0, 'k(3,B,B,B)', '00', null]
- [66, 'IteratorOpen', 4, 0, 38, '', '00', null]
- [67, 'Null', 0, 39, 44, '', '00', null]
- [68, 'IteratorOpen', 14, 0, 0, 'space<name=usercats>', '02', null]
- [69, 'String8', 0, 45, 0, 'af07e444-44f3-4116-833e-90af7f24ffa0', '00', null]
- [70, 'ApplyType', 45, 1, 0, "\x02", '00', null]
- [71, 'SeekGE', 14, 83, 45, '1', '00', null]
- [72, 'IdxGT', 14, 83, 45, '1', '00', null]
- [73, 'Column', 14, 5, 46, '', '00', null]
- [74, 'CollSeq', 0, 0, 0, '(binary)', '00', null]
- [75, 'AggStep0', 0, 46, 39, 'MAX(1)', '01', null]
- [76, 'Column', 14, 4, 46, '', '00', null]
- [77, 'CollSeq', 0, 0, 0, '(binary)', '00', null]
- [78, 'AggStep0', 0, 46, 40, 'MAX(1)', '01', null]
- [79, 'Column', 14, 3, 46, '', '00', null]
- [80, 'CollSeq', 0, 0, 0, '(binary)', '00', null]
- [81, 'AggStep0', 0, 46, 41, 'MAX(1)', '01', null]
- [82, 'Next', 14, 72, 0, '', '00', null]
- [83, 'AggFinal', 39, 1, 0, 'MAX(1)', '00', null]
- [84, 'AggFinal', 40, 1, 0, 'MAX(1)', '00', null]
- [85, 'AggFinal', 41, 1, 0, 'MAX(1)', '00', null]
- [86, 'Copy', 39, 51, 0, '', '00', null]
- [87, 'CollSeq', 0, 0, 0, '({type = binary})', '00', null]
- [88, 'BuiltinFunction0', 1, 50, 47, 'GREATEST(-1)', '02', null]
- [89, 'Copy', 40, 53, 0, '', '00', null]
- [90, 'CollSeq', 0, 0, 0, '({type = binary})', '00', null]
- [91, 'BuiltinFunction0', 1, 52, 48, 'GREATEST(-1)', '02', null]
- [92, 'Copy', 41, 55, 0, '', '00', null]
- [93, 'CollSeq', 0, 0, 0, '({type = binary})', '00', null]
- [94, 'BuiltinFunction0', 1, 54, 49, 'GREATEST(-1)', '02', null]
- [95, 'MakeRecord', 47, 3, 46, '', '01', null]
- [96, 'NextIdEphemeral', 38, 60, 0, '', '00', null]
- [97, 'Copy', 47, 57, 2, '', '00', null]
- [98, 'MakeRecord', 57, 4, 56, '', '01', null]
- [99, 'IdxInsert', 56, 38, 0, '', '00', null]
- [100, 'Return', 37, 0, 0, '', '00', null]
- [101, 'OpenTEphemeral', 61, 52, 0, 'k(1,-B)', '00', null]
- [102, 'IteratorOpen', 15, 0, 61, '', '00', null]
- [103, 'Integer', 5, 62, 0, '', '00', null]
- [104, 'MustBeInt', 62, 107, 0, '', '00', null]
- [105, 'Integer', 0, 63, 0, '', '00', null]
- [106, 'Ge', 63, 109, 62, '', '00', null]
- [107, 'SetDiag', 159, 0, 0, 'Failed to execute SQL statement: Only positive integers
are allowed in the LIMIT clause', '00', null]
- [108, 'Halt', -1, 0, 0, '', '00', null]
- [109, 'Eq', 63, 323, 62, '', '00', null]
- [110, 'Integer', 0, 64, 0, '', '00', null]
- [111, 'MustBeInt', 64, 114, 0, '', '00', null]
- [112, 'Integer', 0, 63, 0, '', '00', null]
- [113, 'Ge', 63, 116, 64, '', '00', null]
- [114, 'SetDiag', 159, 0, 0, 'Failed to execute SQL statement: Only positive integers
are allowed in the OFFSET clause', '00', null]
- [115, 'Halt', -1, 0, 0, '', '00', null]
- [116, 'OffsetLimit', 62, 65, 64, '', '00', null]
- [117, 'IteratorOpen', 16, 1, 0, 'space<name=listings>', '02', null]
- [118, 'Integer', 1, 66, 0, '', '00', null]
- [119, 'IsNull', 66, 121, 0, '', '00', null]
- [120, 'MustBeInt', 66, 268, 0, '', '00', null]
- [121, 'SeekGE', 16, 268, 66, '1', '00', null]
- [122, 'IdxGT', 16, 268, 66, '1', '00', null]
- [123, 'Integer', 0, 67, 0, '', '00', null]
- [124, 'Rewind', 1, 264, 0, '', '00', null]
- [125, 'Column', 16, 0, 63, '', '00', null]
- [126, 'Column', 1, 0, 68, '', '00', null]
- [127, 'Ne', 68, 263, 63, '({type = binary})', '18', null]
- [128, 'Integer', 1, 67, 0, '', '00', null]
- [129, 'Rewind', 2, 263, 0, '', '00', null]
- [130, 'Integer', 0, 69, 0, '', '00', null]
- [131, 'Rewind', 3, 259, 0, '', '00', null]
- [132, 'Column', 16, 22, 68, '', '00', null]
- [133, 'Column', 3, 0, 63, '', '00', null]
- [134, 'Ne', 63, 258, 68, '({type = binary})', '18', null]
- [135, 'Integer', 1, 69, 0, '', '00', null]
- [136, 'Rewind', 4, 258, 0, '', '00', null]
- [137, 'Column', 16, 0, 72, '', '00', null]
- [138, 'Column', 16, 1, 73, '', '00', null]
- [139, 'Column', 16, 2, 74, '', '00', null]
- [140, 'Column', 16, 3, 75, '', '00', null]
- [141, 'Column', 16, 4, 76, '', '00', null]
- [142, 'Column', 16, 5, 77, '', '00', null]
- [143, 'Column', 16, 6, 78, '', '00', null]
- [144, 'Column', 16, 7, 79, '', '00', null]
- [145, 'Column', 16, 8, 80, '', '00', null]
- [146, 'Column', 16, 9, 81, '', '00', null]
- [147, 'Column', 16, 10, 82, '', '00', null]
- [148, 'Column', 16, 11, 83, '', '00', null]
- [149, 'Column', 16, 12, 84, '', '00', null]
- [150, 'Column', 16, 13, 85, '', '00', null]
- [151, 'Column', 16, 14, 86, '', '00', null]
- [152, 'Column', 16, 15, 87, '', '00', null]
- [153, 'Column', 16, 16, 88, '', '00', null]
- [154, 'Column', 16, 17, 89, '', '00', null]
- [155, 'Column', 16, 18, 90, '', '00', null]
- [156, 'Column', 16, 19, 91, '', '00', null]
- [157, 'Column', 16, 20, 92, '', '00', null]
- [158, 'Column', 16, 21, 93, '', '00', null]
- [159, 'Column', 16, 22, 94, '', '00', null]
- [160, 'Column', 16, 23, 95, '', '00', null]
- [161, 'Column', 16, 24, 96, '', '00', null]
- [162, 'Column', 16, 25, 97, '', '00', null]
- [163, 'Column', 16, 26, 98, '', '00', null]
- [164, 'Column', 16, 27, 99, '', '00', null]
- [165, 'Column', 16, 28, 100, '', '00', null]
- [166, 'Column', 16, 29, 101, '', '00', null]
- [167, 'Column', 16, 30, 102, '', '00', null]
- [168, 'Column', 16, 31, 103, '', '00', null]
- [169, 'Column', 16, 32, 104, '', '00', null]
- [170, 'Column', 16, 33, 105, '', '00', null]
- [171, 'Column', 16, 34, 106, '', '00', null]
- [172, 'Column', 16, 35, 107, '', '00', null]
- [173, 'Column', 16, 36, 108, '', '00', null]
- [174, 'Column', 16, 37, 109, '', '00', null]
- [175, 'Column', 16, 38, 110, '', '00', null]
- [176, 'Column', 16, 39, 111, '', '00', null]
- [177, 'Column', 1, 0, 112, '', '00', null]
- [178, 'Column', 1, 1, 113, '', '00', null]
- [179, 'Column', 2, 0, 114, '', '00', null]
- [180, 'Column', 3, 0, 115, '', '00', null]
- [181, 'Column', 3, 1, 116, '', '00', null]
- [182, 'Column', 3, 2, 117, '', '00', null]
- [183, 'Column', 3, 3, 118, '', '00', null]
- [184, 'Column', 4, 0, 119, '', '00', null]
- [185, 'Column', 4, 1, 120, '', '00', null]
- [186, 'Column', 4, 2, 121, '', '00', null]
- [187, 'Column', 16, 35, 126, '', '00', null]
- [188, 'SCopy', 114, 132, 0, '', '00', null]
- [189, 'NotNull', 132, 191, 0, '', '00', null]
- [190, 'Integer', 1, 132, 0, '', '00', null]
- [191, 'SCopy', 113, 133, 0, '', '00', null]
- [192, 'NotNull', 133, 194, 0, '', '00', null]
- [193, 'Integer', 0, 133, 0, '', '00', null]
- [194, 'Subtract', 133, 132, 131, '', '00', null]
- [195, 'SCopy', 114, 133, 0, '', '00', null]
- [196, 'NotNull', 133, 198, 0, '', '00', null]
- [197, 'Integer', 1, 133, 0, '', '00', null]
- [198, 'Divide', 133, 131, 130, '', '00', null]
- [199, 'Multiply', 134, 130, 129, '', '00', null]
- [200, 'Multiply', 135, 129, 128, '', '00', null]
- [201, 'Divide', 136, 128, 127, '', '00', null]
- [202, 'Add', 127, 126, 125, '', '00', null]
- [203, 'Column', 16, 7, 139, '', '00', null]
- [204, 'Subtract', 140, 139, 138, '', '00', null]
- [205, 'BuiltinFunction0', 0, 138, 132, 'ABS(1)', '01', null]
- [206, 'Subtract', 132, 137, 131, '', '00', null]
- [207, 'Divide', 141, 131, 133, '', '00', null]
- [208, 'Column', 16, 8, 143, '', '00', null]
- [209, 'Subtract', 144, 143, 139, '', '00', null]
- [210, 'BuiltinFunction0', 0, 139, 138, 'ABS(1)', '01', null]
- [211, 'Subtract', 138, 142, 132, '', '00', null]
- [212, 'Divide', 145, 132, 131, '', '00', null]
- [213, 'Add', 131, 133, 130, '', '00', null]
- [214, 'Multiply', 134, 130, 129, '', '00', null]
- [215, 'Multiply', 146, 129, 128, '', '00', null]
- [216, 'Divide', 136, 128, 127, '', '00', null]
- [217, 'Add', 127, 125, 124, '', '00', null]
- [218, 'SCopy', 118, 132, 0, '', '00', null]
- [219, 'NotNull', 132, 221, 0, '', '00', null]
- [220, 'Integer', 0, 132, 0, '', '00', null]
- [221, 'SCopy', 121, 138, 0, '', '00', null]
- [222, 'NotNull', 138, 224, 0, '', '00', null]
- [223, 'Integer', 1, 138, 0, '', '00', null]
- [224, 'Divide', 138, 132, 133, '', '00', null]
- [225, 'Multiply', 134, 133, 131, '', '00', null]
- [226, 'Multiply', 147, 131, 130, '', '00', null]
- [227, 'Divide', 136, 130, 129, '', '00', null]
- [228, 'Add', 129, 124, 68, '', '00', null]
- [229, 'SCopy', 117, 138, 0, '', '00', null]
- [230, 'NotNull', 138, 232, 0, '', '00', null]
- [231, 'Integer', 0, 138, 0, '', '00', null]
- [232, 'SCopy', 120, 132, 0, '', '00', null]
- [233, 'NotNull', 132, 235, 0, '', '00', null]
- [234, 'Integer', 1, 132, 0, '', '00', null]
- [235, 'Divide', 132, 138, 133, '', '00', null]
- [236, 'Multiply', 134, 133, 131, '', '00', null]
- [237, 'Multiply', 135, 131, 130, '', '00', null]
- [238, 'Divide', 136, 130, 124, '', '00', null]
- [239, 'Add', 124, 68, 63, '', '00', null]
- [240, 'SCopy', 116, 132, 0, '', '00', null]
- [241, 'NotNull', 132, 243, 0, '', '00', null]
- [242, 'Integer', 0, 132, 0, '', '00', null]
- [243, 'SCopy', 119, 138, 0, '', '00', null]
- [244, 'NotNull', 138, 246, 0, '', '00', null]
- [245, 'Integer', 1, 138, 0, '', '00', null]
- [246, 'Divide', 138, 132, 133, '', '00', null]
- [247, 'Multiply', 134, 133, 131, '', '00', null]
- [248, 'Multiply', 147, 131, 130, '', '00', null]
- [249, 'Divide', 136, 130, 68, '', '00', null]
- [250, 'Add', 68, 63, 70, '', '00', null]
- [251, 'Sequence', 15, 71, 0, '', '00', null]
- [252, 'MakeRecord', 70, 52, 123, '', '00', null]
- [253, 'IdxInsert', 123, 61, 0, '', '00', null]
- [254, 'IfNotZero', 65, 257, 0, '', '00', null]
- [255, 'Rewind', 15, 256, 0, '', '00', null]
- [256, 'Delete', 15, 0, 0, '', '00', null]
- [257, 'Next', 4, 137, 0, '', '01', null]
- [258, 'Next', 3, 132, 0, '', '01', null]
- [259, 'IfPos', 69, 262, 0, '', '00', null]
- [260, 'NullRow', 3, 0, 0, '', '00', null]
- [261, 'Goto', 0, 135, 0, '', '00', null]
- [262, 'Next', 2, 130, 0, '', '01', null]
- [263, 'Next', 1, 125, 0, '', '01', null]
- [264, 'IfPos', 67, 267, 0, '', '00', null]
- [265, 'NullRow', 1, 0, 0, '', '00', null]
- [266, 'Goto', 0, 128, 0, '', '00', null]
- [267, 'Next', 16, 122, 1, '', '00', null]
- [268, 'Last', 15, 323, 0, '', '00', null]
- [269, 'IfPos', 64, 322, 1, '', '00', null]
- [270, 'Column', 15, 0, 72, '', '00', null]
- [271, 'Column', 15, 2, 73, '', '00', null]
- [272, 'Column', 15, 3, 74, '', '00', null]
- [273, 'Column', 15, 4, 75, '', '00', null]
- [274, 'Column', 15, 5, 76, '', '00', null]
- [275, 'Column', 15, 6, 77, '', '00', null]
- [276, 'Column', 15, 7, 78, '', '00', null]
- [277, 'Column', 15, 8, 79, '', '00', null]
- [278, 'Column', 15, 9, 80, '', '00', null]
- [279, 'Column', 15, 10, 81, '', '00', null]
- [280, 'Column', 15, 11, 82, '', '00', null]
- [281, 'Column', 15, 12, 83, '', '00', null]
- [282, 'Column', 15, 13, 84, '', '00', null]
- [283, 'Column', 15, 14, 85, '', '00', null]
- [284, 'Column', 15, 15, 86, '', '00', null]
- [285, 'Column', 15, 16, 87, '', '00', null]
- [286, 'Column', 15, 17, 88, '', '00', null]
- [287, 'Column', 15, 18, 89, '', '00', null]
- [288, 'Column', 15, 19, 90, '', '00', null]
- [289, 'Column', 15, 20, 91, '', '00', null]
- [290, 'Column', 15, 21, 92, '', '00', null]
- [291, 'Column', 15, 22, 93, '', '00', null]
- [292, 'Column', 15, 23, 94, '', '00', null]
- [293, 'Column', 15, 24, 95, '', '00', null]
- [294, 'Column', 15, 25, 96, '', '00', null]
- [295, 'Column', 15, 26, 97, '', '00', null]
- [296, 'Column', 15, 27, 98, '', '00', null]
- [297, 'Column', 15, 28, 99, '', '00', null]
- [298, 'Column', 15, 29, 100, '', '00', null]
- [299, 'Column', 15, 30, 101, '', '00', null]
- [300, 'Column', 15, 31, 102, '', '00', null]
- [301, 'Column', 15, 32, 103, '', '00', null]
- [302, 'Column', 15, 33, 104, '', '00', null]
- [303, 'Column', 15, 34, 105, '', '00', null]
- [304, 'Column', 15, 35, 106, '', '00', null]
- [305, 'Column', 15, 36, 107, '', '00', null]
- [306, 'Column', 15, 37, 108, '', '00', null]
- [307, 'Column', 15, 38, 109, '', '00', null]
- [308, 'Column', 15, 39, 110, '', '00', null]
- [309, 'Column', 15, 40, 111, '', '00', null]
- [310, 'Column', 15, 41, 112, '', '00', null]
- [311, 'Column', 15, 42, 113, '', '00', null]
- [312, 'Column', 15, 43, 114, '', '00', null]
- [313, 'Column', 15, 44, 115, '', '00', null]
- [314, 'Column', 15, 45, 116, '', '00', null]
- [315, 'Column', 15, 46, 117, '', '00', null]
- [316, 'Column', 15, 47, 118, '', '00', null]
- [317, 'Column', 15, 48, 119, '', '00', null]
- [318, 'Column', 15, 49, 120, '', '00', null]
- [319, 'Column', 15, 50, 121, '', '00', null]
- [320, 'Column', 15, 51, 122, '', '00', null]
- [321, 'ResultRow', 72, 51, 0, '', '00', null]
- [322, 'Prev', 15, 269, 0, '', '00', null]
- [323, 'Halt', 0, 0, 0, '', '00', null]
- [324, 'Integer', 1, 18, 0, '', '00', null]
- [325, 'Integer', 1, 50, 0, '', '00', null]
- [326, 'Integer', 1, 52, 0, '', '00', null]
- [327, 'Integer', 1, 54, 0, '', '00', null]
- [328, 'Real', 0, 134, 0, '100', '00', null]
- [329, 'Real', 0, 135, 0, '5.28000020980835', '00', null]
- [330, 'Real', 0, 136, 0, '100.010002136', '00', null]
- [331, 'Integer', 180, 137, 0, '', '00', null]
- [332, 'Real', 0, 140, 0, '-5.796658992767334', '00', null]
- [333, 'Real', 0, 141, 0, '360', '00', null]
- [334, 'Integer', 360, 142, 0, '', '00', null]
- [335, 'Real', 0, 144, 0, '106.4992752075195', '00', null]
- [336, 'Real', 0, 145, 0, '720', '00', null]
- [337, 'Real', 0, 146, 0, '22.28000068664551', '00', null]
- [338, 'Integer', 0, 147, 0, '', '00', null]
- [339, 'Goto', 0, 1, 0, '', '00', null]
...
the original query (previously using subqueries like (SELECT "max_click" FROM mopq) but it gives longer explain compared to CROSS JOIN:
WITH sc AS ( -- shown count
SELECT "ref_id"
, "view_count"
FROM "userlistings"
WHERE "user_id" = 'af07e444-44f3-4116-833e-90af7f24ffa0'
), msc AS (
SELECT GREATEST(1,MAX("view_count")) "max_view"
FROM sc
)
,
opq AS (
SELECT "cat_id"
, "click_interest" -- SPEC-Q
, "purchase_interest" -- SPEC-P
, "message_interest" -- SPEC-O
FROM "usercats"
WHERE "user_id" = 'af07e444-44f3-4116-833e-90af7f24ffa0'
), mopq AS (
SELECT GREATEST(1,MAX("click_interest")) "max_click"
, GREATEST(1,MAX("purchase_interest")) "max_purchase"
, GREATEST(1,MAX("message_interest")) "max_inquiry"
FROM opq
)
SELECT "initial_cache"
+ (IFNULL(msc."max_view",1) - IFNULL(sc."view_count",0)) / IFNULL(msc."max_view",1) * 100.0 * 5.28000020980835/100.010002136
+ ((180-abs("lat" - -5.796658992767334))/360.0 + (360-abs("long" - 106.49927520751953))/720.0) * 100.0 * 22.280000686645508/100.010002136
+ IFNULL("message_interest",0) / IFNULL(mopq."max_inquiry",1) * 100.0 * 0/100.010002136
+ IFNULL("purchase_interest",0) / IFNULL(mopq."max_purchase",1) * 100.0 * 5.28000020980835/100.010002136
+ IFNULL("click_interest",0) / IFNULL(mopq."max_click",1) * 100.0 * 0/100.010002136, *
FROM "listings"
LEFT JOIN sc
ON "listings"."ref_id" = sc."ref_id"
CROSS JOIN msc
LEFT JOIN opq
ON "listings"."categories" = opq."cat_id"
CROSS JOIN mopq
WHERE "ref_type" = 1
ORDER BY 1 DESC LIMIT 5 OFFSET 0
this query took a bit weird duration (measured in the go program, but it would took much time to deploy each time I need change the query):
ref_type = 1 (3538 rows) 587ms
ref_type = 5 ( 886 rows) 142ms
ref_type = 3 ( 104 rows) 9ms
ref_type = 6 (1608 rows) 276ms

Agreed that it's unfortunate and inconvenient, and we plan to make it more convenient in the rather short-term.
As a dirty work-around today I could suggest you to enable VDBE_PROFILE and recompile Tarantool, this would generate annotated with run-time information VDBE log of queries executed to the vdbe_profile.out file, where you would see both timings and counters.
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 999ac4749..0126f5af3 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
## -222,6 +222,7 ## if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DSQL_DEBUG=1)
endif()
add_definitions(-DSQL_TEST=1)
+add_definitions(-DVDBE_PROFILE=1)
set(EXT_SRC_DIR ${CMAKE_SOURCE_DIR}/extra)
set(EXT_BIN_DIR ${CMAKE_BINARY_DIR}/extra)

There's no native (i.e. SQL-like) way to measure query execution time. However, you are able to wrap your query in Lua function, which tracks time (using os Lua module). Example is taken from SQL reference:
function main_function()
local string_value, t, sql_statement
for i = 1,1000000, 1 do
string_value = string_function()
sql_statement = "INSERT INTO tester VALUES (" .. i .. ",'" .. string_value .. "')"
box.execute(sql_statement)
end
end
start_time = os.clock()
main_function()
end_time = os.clock()
'insert done in ' .. end_time - start_time .. ' seconds'
Feel free to open feature request on github: https://github.com/tarantool/tarantool/issues/new

Modified from NikitaRock's answer, create a helper function like this T:
> function T(sql_statement)
start_time = os.clock()
res = box.execute(sql_statement)
end_time = os.clock()
return box.tuple.new(res, 'Query done in ' .. string.format("%.2f",(end_time - start_time)*1000) .. ' ms')
end
> T 'SELECT COUNT(*) FROM "listings" WHERE "ref_type" = 6;'
---
- [{'metadata': [{'name': 'COLUMN_1', 'type': 'integer'}], 'rows': [[1608]]}, 'Query
done in 0.49 ms']
...

Related

Validate credentials against AD with Elixir/Erlang

I'm trying to achieve simple AD Credential Validation with Elixir/Erlang. My code in C# works fine.
C#
private static void Main(string[] args)
{
try
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "132.10.100.156"))
{
bool isValid = pc.ValidateCredentials("my-username", "my-password");
Console.WriteLine(isValid);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadLine();
}
Elixir
defmodule AD do
#moduledoc false
require Logger
#format [
limit: :infinity,
pretty: true,
structs: true,
width: 210,
syntax_colors: [number: :yellow, atom: :cyan, string: :green, boolean: :magenta, nil: :magenta]
]
def test do
{:ok, pid} = :eldap.open(['132.10.100.156'], log: &log/3)
:eldap.simple_bind(pid, 'my-username', 'my-password')
end
def log(_, format_string, format_args) do
Logger.debug(inspect({format_string, format_args}, #format))
end
end
Console:
iex> AD.test
[2019-11-16 18:23:53.354] {'bind request = ~p~n', [{:BindRequest, 3, 'my-username', {:simple, 'my-password'}}]}
{:error, :invalidCredentials}
[2019-11-16 18:23:53.511] {'bind reply = ~p~n',
[
ok: {:LDAPMessage, 1,
{:bindResponse,
{:BindResponse, :invalidCredentials, [],
[56, 48, 48, 57, 48, 51, 48, 56, 58, 32, 76, 100, 97, 112, 69, 114, 114, 58, 32, 68, 83, 73, 68, 45, 48, 67, 48, 57, 48, 51, 67, 56, 44, 32, 99, 111, 109, 109, 101, 110, 116, 58, 32, 65, 99, 99, 101, 112,
116, 83, 101, 99, 117, 114, 105, 116, 121, 67, 111, 110, 116, 101, 120, 116, 32, 101, 114, 114, 111, 114, 44, 32, 100, 97, 116, 97, 32, 53, 50, 101, 44, 32, 118, 50, 53, 56, 48, 0], :asn1_NOVALUE,
:asn1_NOVALUE}}, :asn1_NOVALUE}
]}
iex>
:erldap requires my-username#somedomain or a full DN in order to work correctly.

Convert from byte array to Image

I have data of length 498, and I want to convert it to an image. The data (byte array) is:
ba = [4, 41, 80, 3, 41, 130, 134, 225, 196, 184, 63, 255, 137, 50, 182, 95, 3, 86, 250, 7, 218, 114, 246, 93, 132, 101, 56, 224, 233, 234, 185, 149, 132, 245, 245, 239, 1, 171, 245, 214, 66, 198, 133, 254, 18, 19, 247, 92, 72, 151, 118, 152, 21, 131, 248, 128, 74, 103, 172, 72, 37, 163, 233, 146, 196, 54, 244, 15, 85, 91, 229, 89, 195, 22, 64, 200, 73, 131, 246, 215, 133, 166, 137, 237, 85, 27, 246, 85, 68, 70, 122, 208, 134, 179, 246, 77, 199, 119, 246, 184, 145, 147, 247, 73, 143, 217, 240, 152, 149, 3, 56, 8, 183, 58, 13, 10, 181, 131, 248, 29, 80, 8, 1, 1, 217, 131, 248, 32, 11, 248, 250, 232, 245, 99, 245, 83, 196, 22, 192, 183, 21, 156, 246, 60, 74, 104, 106, 209, 14, 212, 233, 155, 195, 248, 247, 231, 21, 236, 245, 66, 136, 87, 102, 201, 33, 92, 233, 149, 1, 200, 185, 224, 50, 100, 248, 31, 8, 184, 120, 7, 62, 20, 247, 52, 9, 136, 108, 201, 62, 4, 248, 33, 11, 185, 116, 239, 105, 156, 246, 179, 78, 40, 203, 45, 121, 204, 248, 156, 196, 117, 77, 215, 138, 20, 247, 175, 77, 57, 203, 221, 149, 156, 213, 40, 28, 186, 108, 36, 182, 252, 248, 145, 7, 185, 139, 200, 210, 180, 248, 142, 199, 167, 139, 200, 209, 252, 233, 140, 70, 248, 197, 208, 233, 12, 246, 155, 140, 105, 151, 168, 9, 213, 246, 143, 8, 152, 215, 200, 26, 29, 233, 130, 132, 249, 71, 233, 38, 37, 248, 134, 7, 199, 5, 217, 73, 69, 248, 128, 197, 214, 3, 225, 133, 93, 247, 126, 131, 215, 1, 225, 158, 237, 247, 4, 65, 7, 194, 39, 73, 28, 117, 86, 133, 198, 255, 127, 121, 165, 117, 121, 194, 24, 126, 250, 161, 45, 121, 125, 128, 246, 193, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 249, 99, 35, 114, 51, 162, 86, 36, 33, 70, 65, 51, 69, 116, 52, 70, 70, 50, 83, 34, 54, 83, 49, 63, 67, 34, 50, 85, 109, 48, 245, 50, 98, 134, 49, 101, 1, 63, 95, 66, 101, 19, 51, 35, 55, 52, 113, 100, 82, 86, 18, 35, 114, 49, 20, 134, 67, 20, 115, 246, 36, 49, 68, 53, 19, 65, 33, 69, 52, 38, 65, 115, 19, 21, 53, 83, 68, 82, 50, 68, 113, 51, 67, 65, 47, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 211, 203]
I tried using
Image.frombuffer('L', (498), ba, 'raw', 'L', 0, 1)
But, this gave an error saying 'size must be a tuple', I tried giving (498,0) and (0,498), this gave no error, but while saving the image there was an error as 'SystemError: tile cannot extend outside image'.
You can try fromarray function
import numpy as np
image = Image.fromarray(np.array(ba).reshape(498,1))

appIdentityService.signForApp (Java) and app_identity.sign_blob (Python) results are different

I need to sign JWT using Google Cloud appIdentity.
I tried using python agent and it is working. But the Java client gives signature error.
So I run test code to get signature of same input from Java and Python. It returns different result.
python code
import array
from google.appengine.api import app_identity
header_and_payload = "test"
(key_name, signature) = app_identity.sign_blob(header_and_payload)
print array.array('B', signature)
java code
import com.google.appengine.api.appidentity.AppIdentityService;
import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
headerAndPayload = "test";
AppIdentityService appIdentityService = AppIdentityServiceFactory.getAppIdentityService();
AppIdentityService.SigningResult signingResult = appIdentityService.signForApp(headerAndPayload.getBytes());
System.out.println(Arrays.toString(signingResult.getSignature()));
Python output
[205, 130, 214, 28, 19, 7, 233, 69, 92, 161, 8, 160, 36, 162, 149, 125, 5, 100, 8, 219, 244, 235, 188, 126, 118, 45, 176, 63, 61, 88, 91, 151, 151, 114, 228, 31, 85, 209, 117, 134, 66, 120, 13, 159, 10, 155, 70, 16, 110, 56, 212, 79, 165, 40, 222, 46, 26, 74, 182, 80, 223, 57, 244, 44, 224, 122, 230, 184, 114, 236, 158, 204, 145, 152, 133, 131, 115, 43, 224, 132, 219, 232, 186, 237, 82, 86, 243, 194, 155, 127, 26, 227, 19, 165, 142, 216, 238, 163, 99, 251, 41, 191, 164, 206, 85, 239, 64, 133, 41, 49, 120, 235, 120, 226, 96, 224, 105, 68, 81, 186, 184, 65, 233, 129, 211, 231, 211, 135, 15, 88, 35, 20, 217, 95, 56, 215, 134, 71, 210, 28, 43, 22, 231, 69, 134, 116, 227, 161, 202, 94, 54, 222, 132, 158, 108, 45, 73, 68, 240, 90, 59, 139, 222, 118, 6, 82, 162, 198, 143, 7, 233, 148, 233, 232, 101, 135, 182, 71, 148, 136, 246, 168, 5, 28, 94, 11, 10, 78, 147, 4, 200, 36, 79, 244, 117, 223, 114, 33, 2, 206, 13, 66, 204, 201, 102, 147, 237, 83, 83, 17, 221, 16, 136, 206, 115, 141, 32, 149, 131, 136, 183, 96, 51, 31, 212, 174, 245, 120, 18, 120, 191, 174, 90, 111, 122, 136, 96, 152, 81, 8, 72, 52, 33, 46, 227, 241, 41, 77, 40, 176, 97, 189, 195, 197, 202, 71]
java output
[10, -64, 92, 105, 15, 35, -32, -101, 47, 111, -1, -72, 110, 105, -77, -117, 23, 69, 113, -49, -14, -104, 110, 78, 84, -78, 30, 26, 38, -43, 36, 112, 33, -10, -5, -63, -11, 47, -53, -116, -71, 2, -64, -16, 36, 122, 45, 79, 3, 49, -7, 120, -10, 125, 92, 43, -43, -34, 100, 75, -54, -36, 5, 106, -128, 106, -120, 36, 59, -31, -2, 100, 79, 65, -118, -50, -83, 11, -19, -28, -80, -125, -8, 59, -94, -125, 91, -104, -96, -12, 14, 31, -108, 61, 12, 6, 90, -6, -24, -47, -57, 55, -64, -50, 41, 26, -46, -81, -124, 122, 82, -120, 31, 19, 85, -7, -17, 40, -18, -118, -64, 114, -76, -60, 116, -12, -16, 12, -91, 55, -57, -61, 108, 88, -13, 80, -38, 100, 121, -11, -20, -5, -105, 20, 87, 60, -125, 33, -11, 111, -115, -69, 24, 0, -113, -24, 49, 21, -27, 96, 27, 12, 72, 50, 12, 15, -61, -40, -52, -76, -63, 29, -99, 114, 88, 41, 111, 9, 127, 96, -123, 58, 92, -91, 17, 114, -11, -105, -79, -110, -100, -35, 16, 103, 27, -21, -50, 7, -28, 117, 119, -124, -127, -115, -116, 86, 74, 57, -46, 114, 102, -18, -73, 97, 10, -113, 119, -1, -68, -18, -16, -119, 49, -120, 104, 121, 113, -82, -42, -119, -81, 95, -114, 16, -11, -58, 36, -24, 58, -50, 101, -117, -55, -101, -19, 62, -53, 30, -59, 106, 37, 98, 102, 75, -9, 91]
What is the issue in Java code? Thank you.
In the line:
print array.array('B', signature)
you are using the option 'B' for unsigned char according to the docs. If you use the option 'b' (for signed char) like in
print array.array('b', signature)
you will get the same results for both the Java and the python versions.
I performed tests with the sample codes for Python and Java. In the Python example I set the message variable to the same value as in Java:
message = "abcdefg"
and added this line:
self.response.write('Signature Array: {}\n'.format(array.array('b', signature)))
Hope this helps.

How to split byte array into 4 bytes and convert result to float?

I am currently developing a display application for F1 2017 on my iPhone using swift. I am able to read the UDP packets from my PS4 to my phone by using SwiftSockets.
I received the following data:
[25, 79, 3, 64, 176, 153, 15, 61, 244, 133, 165, 69, 0, 20, 145, 192, 223, 145, 218, 194, 165, 106, 64, 64, 15, 88, 234, 67, 220, 222, 109, 59, 168, 219, 67, 187, 42, 245, 4, 59, 200, 163, 186, 57, 65, 126, 46, 63, 22, 207, 77, 59, 13, 81, 59, 191, 127, 79, 59, 191, 0, 73, 203, 187, 141, 126, 46, 191, 180, 81, 37, 190, 5, 254, 41, 189, 251, 167, 151, 62, 145, 185, 39, 62, 7, 210, 92, 63, 203, 186, 128, 192, 218, 25, 99, 64, 112, 21, 0, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 24, 106, 72, 61, 239, 89, 49, 187, 0, 0, 192, 64, 191, 199, 133, 69, 0, 0, 0, 0, 0, 0, 144, 65, 0, 80, 195, 72, 0, 80, 195, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 75, 253, 209, 66, 0, 0, 210, 66, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 80, 182, 232, 65, 80, 182, 232, 65, 80, 182, 232, 65, 80, 182, 232, 65, 0, 0, 172, 65, 0, 0, 172, 65, 0, 0, 184, 65, 0, 0, 184, 65, 0, 0, 0, 64, 0, 0, 198, 66, 57, 170, 165, 69, 128, 93, 205, 66, 0, 128, 84, 70, 0, 96, 134, 69, 0, 0, 16, 65, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 252, 68, 240, 253, 176, 66, 131, 119, 113, 188, 93, 249, 95, 187, 28, 146, 43, 59, 116, 163, 23, 188, 87, 87, 88, 88, 0, 0, 0, 0, 5, 54, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 200, 88, 12, 67, 0, 0, 255, 20, 0, 146, 115, 234, 194, 88, 249, 59, 64, 95, 94, 231, 67, 128, 93, 205, 66, 176, 153, 15, 61, 24, 134, 204, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 122, 64, 100, 2, 18, 7, 5, 0, 0, 0, 0, 245, 73, 129, 193, 65, 222, 85, 64, 134, 169, 0, 68, 32, 234, 205, 66, 224, 188, 92, 67, 94, 87, 203, 66, 0, 0, 0, 0, 0, 0, 0, 0, 62, 112, 162, 69, 34, 2, 15, 3, 5, 1, 2, 0, 0, 134, 253, 181, 65, 69, 178, 83, 64, 5, 6, 10, 68, 136, 6, 200, 66, 70, 194, 141, 67, 180, 236, 199, 66, 0, 0, 0, 0, 0, 0, 0, 0, 17, 208, 160, 69, 16, 0, 5, 3, 5, 1, 2, 0, 0, 16, 137, 185, 195, 194, 6, 44, 64, 211, 20, 153, 66, 64, 15, 198, 66, 238, 232, 27, 61, 64, 15, 198, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 253, 67, 0, 1, 1, 4, 5, 0, 0, 0, 0, 83, 13, 149, 65, 96, 78, 84, 64, 101, 6, 9, 68, 170, 16, 200, 66, 82, 86, 44, 68, 212, 184, 199, 66, 0, 0, 0, 0, 0, 0, 0, 0, 75, 252, 160, 69, 6, 1, 3, 3, 5, 1, 2, 0, 0, 247, 239, 27, 68, 227, 16, 124, 64, 33, 229, 220, 67, 171, 9, 202, 66, 0, 0, 0, 0, 171, 9, 202, 66, 0, 0, 0, 0, 0, 0, 0, 0, 86, 90, 110, 69, 7, 11, 11, 2, 5, 0, 2, 0, 0, 91, 113, 167, 67, 92, 188, 60, 64, 223, 10, 42, 68, 58, 73, 206, 66, 0, 0, 0, 0, 58, 73, 206, 66, 0, 0, 0, 0, 0, 0, 0, 0, 214, 218, 146, 69, 18, 5, 19, 3, 5, 0, 2, 0, 0, 235, 33, 44, 68, 26, 50, 118, 64, 22, 232, 74, 68, 64, 189, 200, 66, 0, 0, 0, 0, 64, 189, 200, 66, 0, 0, 0, 0, 0, 0, 0, 0, 190, 18, 132, 69, 5, 6, 7, 3, 5, 0, 2, 0, 0, 63, 156, 38, 68, 27, 127, 136, 64, 55, 132, 5, 68, 48, 100, 203, 66, 0, 0, 0, 0, 48, 100, 203, 66, 0, 0, 0, 0, 0, 0, 0, 0, 12, 190, 116, 69, 35, 7, 16, 3, 5, 0, 2, 0, 0, 214, 118, 54, 196, 239, 49, 70, 64, 111, 224, 185, 195, 176, 46, 202, 66, 200, 232, 13, 61, 176, 46, 202, 66, 0, 0, 0, 0, 0, 0, 0, 0, 128, 229, 135, 68, 3, 7, 13, 4, 5, 0, 0, 0, 0, 122, 220, 252, 67, 157, 82, 60, 64, 88, 205, 89, 68, 208, 106, 202, 66, 0, 0, 0, 0, 208, 106, 202, 66, 0, 0, 0, 0, 0, 0, 0, 0, 213, 35, 138, 69, 14, 11, 14, 2, 5, 0, 2, 0, 0, 43, 225, 15, 68, 97, 160, 103, 64, 244, 178, 187, 67, 216, 10, 202, 66, 0, 0, 0, 0, 216, 10, 202, 66, 0, 0, 0, 0, 0, 0, 0, 0, 64, 42, 105, 69, 1, 8, 12, 3, 5, 0, 2, 0, 0, 12, 73, 197, 67, 40, 119, 53, 64, 115, 141, 56, 68, 199, 157, 201, 66, 0, 0, 0, 0, 199, 157, 201, 66, 0, 0, 0, 0, 0, 0, 0, 0, 5, 231, 143, 69, 10, 3, 8, 2, 5, 0, 2, 0, 0, 66, 178, 177, 67, 10, 45, 66, 64, 88, 176, 42, 68, 168, 124, 203, 66, 0, 0, 0, 0, 168, 124, 203, 66, 0, 0, 0, 0, 0, 0, 0, 0, 230, 9, 146, 69, 20, 3, 17, 3, 5, 0, 2, 0, 0, 140, 235, 54, 68, 99, 244, 101, 64, 198, 155, 62, 68, 16, 171, 201, 66, 0, 0, 0, 0, 16, 171, 201, 66, 0, 0, 0, 0, 0, 0, 0, 0, 109, 212, 129, 69, 33, 6, 9, 2, 5, 0, 2, 0, 0, 21, 102, 86, 66, 112, 68, 96, 64, 60, 2, 135, 65, 128, 194, 199, 66, 164, 206, 103, 66, 128, 194, 199, 66, 96, 174, 4, 66, 0, 0, 0, 0, 236, 0, 63, 69, 22, 0, 4, 3, 5, 0, 1, 0, 0, 47, 20, 201, 67, 201, 159, 49, 64, 18, 130, 60, 68, 8, 44, 199, 66, 86, 200, 170, 66, 8, 44, 199, 66, 64, 16, 4, 66, 64, 253, 217, 65, 94, 90, 143, 69, 9, 4, 2, 3, 5, 0, 2, 0, 0, 32, 154, 227, 194, 27, 193, 93, 64, 243, 43, 77, 196, 251, 231, 201, 66, 0, 0, 0, 0, 251, 231, 201, 66, 0, 0, 0, 0, 0, 0, 0, 0, 112, 189, 255, 68, 23, 8, 10, 3, 5, 0, 1, 0, 0, 157, 12, 27, 66, 80, 210, 84, 64, 234, 220, 13, 68, 240, 20, 200, 66, 204, 189, 15, 67, 240, 20, 200, 66, 0, 0, 0, 0, 0, 0, 0, 0, 113, 36, 160, 69, 15, 4, 6, 2, 5, 1, 2, 0, 0, 70, 217, 139, 67, 81, 9, 51, 64, 70, 253, 57, 68, 81, 176, 206, 66, 204, 63, 149, 60, 81, 176, 206, 66, 0, 0, 0, 0, 0, 0, 0, 0, 71, 132, 149, 69, 31, 5, 20, 2, 5, 0, 2, 0, 0, 182, 135, 20, 192, 86, 227, 218, 187, 41, 207, 77, 187, 23, 39, 22, 59, 188, 55, 6, 59, 86, 40, 253, 58, 203, 2, 123, 66, 62, 192, 141, 194, 179, 242, 115, 66, 2, 233, 141, 194, 207, 30, 49, 191, 192, 105, 55, 62, 231, 125, 246, 190]
How would I be able to decode the data into a UDPPacket? In order to do this, I think I need to convert the data into four bytes and then somehow convert it to a float.
Here is my swift code:
import UIKit
import SwiftSocket
class ViewController: UIViewController {
var server: UDPServer!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
server = UDPServer(address: "192.168.1.158", port: 20777)
timer = Timer.scheduledTimer(withTimeInterval: 0, repeats: true) { _ in
print("a")
let data = self.server.recv(1289).0
if let data = data {
print(data)
self.timer.invalidate()
}
}
timer.fire()
}
}
This is what the UDPPacket should look like:
struct UDPPacket
{
float m_time;
float m_lapTime;
float m_lapDistance;
float m_totalDistance;
float m_x; // World space position
float m_y; // World space position
float m_z; // World space position
float m_speed; // Speed of car in MPH
float m_xv; // Velocity in world space
float m_yv; // Velocity in world space
float m_zv; // Velocity in world space
float m_xr; // World space right direction
float m_yr; // World space right direction
float m_zr; // World space right direction
float m_xd; // World space forward direction
float m_yd; // World space forward direction
float m_zd; // World space forward direction
float m_susp_pos[4]; // Note: All wheel arrays have the order:
float m_susp_vel[4]; // RL, RR, FL, FR
float m_wheel_speed[4];
float m_throttle;
float m_steer;
float m_brake;
float m_clutch;
float m_gear;
float m_gforce_lat;
float m_gforce_lon;
float m_lap;
float m_engineRate;
float m_sli_pro_native_support; // SLI Pro support
float m_car_position; // car race position
float m_kers_level; // kers energy left
float m_kers_max_level; // kers maximum energy
float m_drs; // 0 = off, 1 = on
float m_traction_control; // 0 (off) - 2 (high)
float m_anti_lock_brakes; // 0 (off) - 1 (on)
float m_fuel_in_tank; // current fuel mass
float m_fuel_capacity; // fuel capacity
float m_in_pits; // 0 = none, 1 = pitting, 2 = in pit area
float m_sector; // 0 = sector1, 1 = sector2, 2 = sector3
float m_sector1_time; // time of sector1 (or 0)
float m_sector2_time; // time of sector2 (or 0)
float m_brakes_temp[4]; // brakes temperature (centigrade)
float m_tyres_pressure[4]; // tyres pressure PSI
float m_team_info; // team ID
float m_total_laps; // total number of laps in this race
float m_track_size; // track size meters
float m_last_lap_time; // last lap time
float m_max_rpm; // cars max RPM, at which point the rev limiter will kick in
float m_idle_rpm; // cars idle RPM
float m_max_gears; // maximum number of gears
float m_sessionType; // 0 = unknown, 1 = practice, 2 = qualifying, 3 = race
float m_drsAllowed; // 0 = not allowed, 1 = allowed, -1 = invalid / unknown
float m_track_number; // -1 for unknown, 0-21 for tracks
float m_vehicleFIAFlags; // -1 = invalid/unknown, 0 = none, 1 = green, 2 = blue, 3 = yellow, 4 = red
float m_era; // era, 2017 (modern) or 1980 (classic)
float m_engine_temperature; // engine temperature (centigrade)
float m_gforce_vert; // vertical g-force component
float m_ang_vel_x; // angular velocity x-component
float m_ang_vel_y; // angular velocity y-component
float m_ang_vel_z; // angular velocity z-component
byte m_tyres_temperature[4]; // tyres temperature (centigrade)
byte m_tyres_wear[4]; // tyre wear percentage
byte m_tyre_compound; // compound of tyre – 0 = ultra soft, 1 = super soft, 2 = soft, 3 = medium, 4 = hard, 5 = inter, 6 = wet
byte m_front_brake_bias; // front brake bias (percentage)
byte m_fuel_mix; // fuel mix - 0 = lean, 1 = standard, 2 = rich, 3 = max
byte m_currentLapInvalid; // current lap invalid - 0 = valid, 1 = invalid
byte m_tyres_damage[4]; // tyre damage (percentage)
byte m_front_left_wing_damage; // front left wing damage (percentage)
byte m_front_right_wing_damage; // front right wing damage (percentage)
byte m_rear_wing_damage; // rear wing damage (percentage)
byte m_engine_damage; // engine damage (percentage)
byte m_gear_box_damage; // gear box damage (percentage)
byte m_exhaust_damage; // exhaust damage (percentage)
byte m_pit_limiter_status; // pit limiter status – 0 = off, 1 = on
byte m_pit_speed_limit; // pit speed limit in mph
float m_session_time_left; // NEW: time left in session in seconds
byte m_rev_lights_percent; // NEW: rev lights indicator (percentage)
byte m_is_spectating; // NEW: whether the player is spectating
byte m_spectator_car_index; // NEW: index of the car being spectated
// Car data
byte m_num_cars; // number of cars in data
byte m_player_car_index; // index of player's car in the array
CarUDPData m_car_data[20]; // data for all cars on track
float m_yaw; // NEW (v1.8)
float m_pitch; // NEW (v1.8)
float m_roll; // NEW (v1.8)
float m_x_local_velocity; // NEW (v1.8) Velocity in local space
float m_y_local_velocity; // NEW (v1.8) Velocity in local space
float m_z_local_velocity; // NEW (v1.8) Velocity in local space
float m_susp_acceleration[4]; // NEW (v1.8) RL, RR, FL, FR
float m_ang_acc_x; // NEW (v1.8) angular acceleration x-component
float m_ang_acc_y; // NEW (v1.8) angular acceleration y-component
float m_ang_acc_z; // NEW (v1.8) angular acceleration z-component
};
CarUDPData:
struct CarUDPData
{
float m_worldPosition[3]; // world co-ordinates of vehicle
float m_lastLapTime;
float m_currentLapTime;
float m_bestLapTime;
float m_sector1Time;
float m_sector2Time;
float m_lapDistance;
byte m_driverId;
byte m_teamId;
byte m_carPosition; // UPDATED: track positions of vehicle
byte m_currentLapNum;
byte m_tyreCompound; // compound of tyre – 0 = ultra soft, 1 = super soft, 2 = soft, 3 = medium, 4 = hard, 5 = inter, 6 = wet
byte m_inPits; // 0 = none, 1 = pitting, 2 = in pit area
byte m_sector; // 0 = sector1, 1 = sector2, 2 = sector3
byte m_currentLapInvalid; // current lap invalid - 0 = valid, 1 = invalid
byte m_penalties; // NEW: accumulated time penalties in seconds to be added
};
If it helps, I am at the start of a Grand Prix (not career), racing as Lewis Hamilton at Australia and the starting lights have not gone off yet.
Here is a link to the UDP data specifications for F1 2017.

sine function on 16-bit microcontroller

I need to generate a sine wave to fill a char table of size 1024. The word size on the microcontroller is 16-bit and floating-point operations are not available.
The sine wave itself will oscillate between the value of 0 to 255, with 127 being the center point.
Any ideas?
You only actually need to store one quarter of the sine wave -- you can lookup the other three quarters from the first quadrant. So you only need 256 bytes.
To generate the values on the micro controller, implement CORDIC. You can store one value, and generate the whole sine wave from that.
Create a precomputed array on your PC. You only have to create a fourth of the array if ROM (or equivalent, such as flash or code segment) space is at a premium, then mirror this part out to the other 768 bytes of the array.
Write a sin table generator in your favorite language using float.
Scale and round the results to desired ranges 1024/-127..+128 (you may do that right away).
From the table, generate a source file in ASM or C, what ever works better for you.
Make sure the generated table in marked "const" in C or make go to a approbiate section in ASM so it goes to FLASH rather than RAM.
Include the file in your project.
Now intsin(x)1 is:
int intsin(int x)
limit x // 0..360° or 2PI
scale to 1024
read table at x
return x
You can improve resolution by using the table for the first quadrant only. You can than use positive values only, too (0..255). Then your intsin(x) would need to determine the quadrant and mirror the first quadrant results.
You just generate table on your PC and use it on your MCU. As somebody said you just need a quater period, but to answer your question fully, here are all 1024 chars:
for k := 0 to 1023 do
buffer[k] := (round(128+127*sin(2*pi*k/1024)));
128, 129, 130, 130, 131, 132, 133, 133, 134, 135, 136, 137, 137, 138, 139, 140, 140,
141, 142, 143, 144, 144, 145, 146, 147, 147, 148, 149, 150, 150, 151, 152, 153,
154, 154, 155, 156, 157, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, 165,
166, 166, 167, 168, 169, 169, 170, 171, 172, 172, 173, 174, 174, 175, 176, 177,
177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 184, 185, 186, 186, 187, 188,
189, 189, 190, 191, 191, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199,
199, 200, 200, 201, 202, 202, 203, 204, 204, 205, 206, 206, 207, 207, 208, 209,
209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 216, 216, 217, 217, 218,
218, 219, 219, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 225, 226, 226,
227, 227, 228, 228, 229, 229, 230, 230, 230, 231, 231, 232, 232, 233, 233, 234,
234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 239, 240, 240,
240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245,
246, 246, 246, 246, 247, 247, 247, 248, 248, 248, 248, 249, 249, 249, 249, 250,
250, 250, 250, 250, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 253,
253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254,
254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253, 253, 253, 253, 253, 253,
252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 250, 250, 250, 250, 250,
249, 249, 249, 249, 248, 248, 248, 248, 247, 247, 247, 246, 246, 246, 246, 245,
245, 245, 244, 244, 244, 243, 243, 243, 242, 242, 242, 241, 241, 241, 240, 240,
240, 239, 239, 239, 238, 238, 237, 237, 237, 236, 236, 235, 235, 234, 234, 234,
233, 233, 232, 232, 231, 231, 230, 230, 230, 229, 229, 228, 228, 227, 227, 226,
226, 225, 225, 224, 224, 223, 223, 222, 222, 221, 221, 220, 219, 219, 218, 218,
217, 217, 216, 216, 215, 214, 214, 213, 213, 212, 212, 211, 210, 210, 209, 209,
208, 207, 207, 206, 206, 205, 204, 204, 203, 202, 202, 201, 200, 200, 199, 199,
198, 197, 197, 196, 195, 195, 194, 193, 193, 192, 191, 191, 190, 189, 189, 188,
187, 186, 186, 185, 184, 184, 183, 182, 182, 181, 180, 179, 179, 178, 177, 177,
176, 175, 174, 174, 173, 172, 172, 171, 170, 169, 169, 168, 167, 166, 166, 165,
164, 163, 163, 162, 161, 160, 160, 159, 158, 157, 157, 156, 155, 154, 154, 153,
152, 151, 150, 150, 149, 148, 147, 147, 146, 145, 144, 144, 143, 142, 141, 140,
140, 139, 138, 137, 137, 136, 135, 134, 133, 133, 132, 131, 130, 130, 129, 128,
127, 126, 126, 125, 124, 123, 123, 122, 121, 120, 119, 119, 118, 117, 116, 116,
115, 114, 113, 112, 112, 111, 110, 109, 109, 108, 107, 106, 106, 105, 104, 103,
102, 102, 101, 100, 99, 99, 98, 97, 96, 96, 95, 94, 93, 93, 92, 91,
90, 90, 89, 88, 87, 87, 86, 85, 84, 84, 83, 82, 82, 81, 80, 79,
79, 78, 77, 77, 76, 75, 74, 74, 73, 72, 72, 71, 70, 70, 69, 68,
67, 67, 66, 65, 65, 64, 63, 63, 62, 61, 61, 60, 59, 59, 58, 57,
57, 56, 56, 55, 54, 54, 53, 52, 52, 51, 50, 50, 49, 49, 48, 47,
47, 46, 46, 45, 44, 44, 43, 43, 42, 42, 41, 40, 40, 39, 39, 38,
38, 37, 37, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30,
29, 29, 28, 28, 27, 27, 26, 26, 26, 25, 25, 24, 24, 23, 23, 22,
22, 22, 21, 21, 20, 20, 19, 19, 19, 18, 18, 17, 17, 17, 16, 16,
16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11,
10, 10, 10, 10, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6,
6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3,
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11,
11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16,
16, 17, 17, 17, 18, 18, 19, 19, 19, 20, 20, 21, 21, 22, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 26, 27, 27, 28, 28, 29, 29, 30,
30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 37, 37, 38, 38,
39, 39, 40, 40, 41, 42, 42, 43, 43, 44, 44, 45, 46, 46, 47, 47,
48, 49, 49, 50, 50, 51, 52, 52, 53, 54, 54, 55, 56, 56, 57, 57,
58, 59, 59, 60, 61, 61, 62, 63, 63, 64, 65, 65, 66, 67, 67, 68,
69, 70, 70, 71, 72, 72, 73, 74, 74, 75, 76, 77, 77, 78, 79, 79,
80, 81, 82, 82, 83, 84, 84, 85, 86, 87, 87, 88, 89, 90, 90, 91,
92, 93, 93, 94, 95, 96, 96, 97, 98, 99, 99, 100, 101, 102, 102, 103,
104, 105, 106, 106, 107, 108, 109, 109, 110, 111, 112, 112, 113, 114, 115, 116,
116, 117, 118, 119, 119, 120, 121, 122, 123, 123, 124, 125, 126, 126, 127

Resources