Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
eec2835d
Commit
eec2835d
authored
Jun 16, 2004
by
unknown
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tux optim 2 - use physical TUP address for index nodes
parent
0300c895
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
403 additions
and
336 deletions
+403
-336
ndb/include/kernel/signaldata/TupAccess.hpp
ndb/include/kernel/signaldata/TupAccess.hpp
+4
-2
ndb/src/kernel/blocks/dbtux/Dbtux.hpp
ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+222
-176
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+28
-13
ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+7
-10
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+3
-2
ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
+13
-13
ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+28
-28
ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
+89
-90
ndb/src/kernel/blocks/dbtux/Times.txt
ndb/src/kernel/blocks/dbtux/Times.txt
+9
-2
No files found.
ndb/include/kernel/signaldata/TupAccess.hpp
View file @
eec2835d
...
@@ -129,6 +129,8 @@ private:
...
@@ -129,6 +129,8 @@ private:
/*
/*
* Operate on entire tuple. Used by TUX where the table has a single
* Operate on entire tuple. Used by TUX where the table has a single
* Uint32 array attribute representing an index tree node.
* Uint32 array attribute representing an index tree node.
*
* XXX this signal will be replaced by method in TUP
*/
*/
class
TupStoreTh
{
class
TupStoreTh
{
friend
class
Dbtup
;
friend
class
Dbtup
;
...
@@ -153,8 +155,8 @@ private:
...
@@ -153,8 +155,8 @@ private:
Uint32
tableId
;
Uint32
tableId
;
Uint32
fragId
;
Uint32
fragId
;
Uint32
fragPtrI
;
Uint32
fragPtrI
;
Uint32
tupAddr
;
Uint32
tupAddr
;
// no longer used
Uint32
tupVersion
;
Uint32
tupVersion
;
// no longer used
Uint32
pageId
;
Uint32
pageId
;
Uint32
pageOffset
;
Uint32
pageOffset
;
Uint32
bufferId
;
Uint32
bufferId
;
...
...
ndb/src/kernel/blocks/dbtux/Dbtux.hpp
View file @
eec2835d
This diff is collapsed.
Click to expand it.
ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
View file @
eec2835d
...
@@ -97,7 +97,7 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
...
@@ -97,7 +97,7 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
PrintPar
par
;
PrintPar
par
;
strcpy
(
par
.
m_path
,
"."
);
strcpy
(
par
.
m_path
,
"."
);
par
.
m_side
=
2
;
par
.
m_side
=
2
;
par
.
m_parent
=
NullTup
Addr
;
par
.
m_parent
=
NullTup
Loc
;
printNode
(
signal
,
frag
,
out
,
tree
.
m_root
,
par
);
printNode
(
signal
,
frag
,
out
,
tree
.
m_root
,
par
);
out
.
m_out
->
flush
();
out
.
m_out
->
flush
();
if
(
!
par
.
m_ok
)
{
if
(
!
par
.
m_ok
)
{
...
@@ -116,15 +116,15 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
...
@@ -116,15 +116,15 @@ Dbtux::printTree(Signal* signal, Frag& frag, NdbOut& out)
}
}
void
void
Dbtux
::
printNode
(
Signal
*
signal
,
Frag
&
frag
,
NdbOut
&
out
,
Tup
Addr
addr
,
PrintPar
&
par
)
Dbtux
::
printNode
(
Signal
*
signal
,
Frag
&
frag
,
NdbOut
&
out
,
Tup
Loc
loc
,
PrintPar
&
par
)
{
{
if
(
addr
==
NullTupAddr
)
{
if
(
loc
==
NullTupLoc
)
{
par
.
m_depth
=
0
;
par
.
m_depth
=
0
;
return
;
return
;
}
}
TreeHead
&
tree
=
frag
.
m_tree
;
TreeHead
&
tree
=
frag
.
m_tree
;
NodeHandlePtr
nodePtr
;
NodeHandlePtr
nodePtr
;
selectNode
(
signal
,
frag
,
nodePtr
,
addr
,
AccFull
);
selectNode
(
signal
,
frag
,
nodePtr
,
loc
,
AccFull
);
out
<<
par
.
m_path
<<
" "
<<
*
nodePtr
.
p
<<
endl
;
out
<<
par
.
m_path
<<
" "
<<
*
nodePtr
.
p
<<
endl
;
// check children
// check children
PrintPar
cpar
[
2
];
PrintPar
cpar
[
2
];
...
@@ -133,7 +133,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
...
@@ -133,7 +133,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
sprintf
(
cpar
[
i
].
m_path
,
"%s%c"
,
par
.
m_path
,
"LR"
[
i
]);
sprintf
(
cpar
[
i
].
m_path
,
"%s%c"
,
par
.
m_path
,
"LR"
[
i
]);
cpar
[
i
].
m_side
=
i
;
cpar
[
i
].
m_side
=
i
;
cpar
[
i
].
m_depth
=
0
;
cpar
[
i
].
m_depth
=
0
;
cpar
[
i
].
m_parent
=
addr
;
cpar
[
i
].
m_parent
=
loc
;
printNode
(
signal
,
frag
,
out
,
nodePtr
.
p
->
getLink
(
i
),
cpar
[
i
]);
printNode
(
signal
,
frag
,
out
,
nodePtr
.
p
->
getLink
(
i
),
cpar
[
i
]);
if
(
!
cpar
[
i
].
m_ok
)
{
if
(
!
cpar
[
i
].
m_ok
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
...
@@ -143,7 +143,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
...
@@ -143,7 +143,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
if
(
nodePtr
.
p
->
getLink
(
2
)
!=
par
.
m_parent
)
{
if
(
nodePtr
.
p
->
getLink
(
2
)
!=
par
.
m_parent
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
"parent
addr
"
<<
hex
<<
nodePtr
.
p
->
getLink
(
2
);
out
<<
"parent
loc
"
<<
hex
<<
nodePtr
.
p
->
getLink
(
2
);
out
<<
" should be "
<<
hex
<<
par
.
m_parent
<<
endl
;
out
<<
" should be "
<<
hex
<<
par
.
m_parent
<<
endl
;
}
}
if
(
nodePtr
.
p
->
getSide
()
!=
par
.
m_side
)
{
if
(
nodePtr
.
p
->
getSide
()
!=
par
.
m_side
)
{
...
@@ -181,8 +181,8 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
...
@@ -181,8 +181,8 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
}
}
// check missed half-leaf/leaf merge
// check missed half-leaf/leaf merge
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
if
(
nodePtr
.
p
->
getLink
(
i
)
!=
NullTup
Addr
&&
if
(
nodePtr
.
p
->
getLink
(
i
)
!=
NullTup
Loc
&&
nodePtr
.
p
->
getLink
(
1
-
i
)
==
NullTup
Addr
&&
nodePtr
.
p
->
getLink
(
1
-
i
)
==
NullTup
Loc
&&
nodePtr
.
p
->
getOccup
()
+
cpar
[
i
].
m_occup
<=
tree
.
m_maxOccup
)
{
nodePtr
.
p
->
getOccup
()
+
cpar
[
i
].
m_occup
<=
tree
.
m_maxOccup
)
{
par
.
m_ok
=
false
;
par
.
m_ok
=
false
;
out
<<
par
.
m_path
<<
" *** "
;
out
<<
par
.
m_path
<<
" *** "
;
...
@@ -194,6 +194,18 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
...
@@ -194,6 +194,18 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupAddr addr, PrintPar
par
.
m_occup
=
nodePtr
.
p
->
getOccup
();
par
.
m_occup
=
nodePtr
.
p
->
getOccup
();
}
}
NdbOut
&
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TupLoc
&
loc
)
{
if
(
loc
==
Dbtux
::
NullTupLoc
)
{
out
<<
"null"
;
}
else
{
out
<<
hex
<<
loc
.
m_pageId
;
out
<<
"."
<<
dec
<<
loc
.
m_pageOffset
;
}
return
out
;
}
NdbOut
&
NdbOut
&
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TreeEnt
&
ent
)
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TreeEnt
&
ent
)
{
{
...
@@ -206,10 +218,13 @@ operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
...
@@ -206,10 +218,13 @@ operator<<(NdbOut& out, const Dbtux::TreeEnt& ent)
NdbOut
&
NdbOut
&
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TreeNode
&
node
)
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TreeNode
&
node
)
{
{
Dbtux
::
TupLoc
link0
(
node
.
m_linkPI
[
0
],
node
.
m_linkPO
[
0
]);
Dbtux
::
TupLoc
link1
(
node
.
m_linkPI
[
1
],
node
.
m_linkPO
[
1
]);
Dbtux
::
TupLoc
link2
(
node
.
m_linkPI
[
2
],
node
.
m_linkPO
[
2
]);
out
<<
"[TreeNode "
<<
hex
<<
&
node
;
out
<<
"[TreeNode "
<<
hex
<<
&
node
;
out
<<
" [left "
<<
hex
<<
node
.
m_link
[
0
]
<<
"]"
;
out
<<
" [left "
<<
link0
<<
"]"
;
out
<<
" [right "
<<
hex
<<
node
.
m_link
[
1
]
<<
"]"
;
out
<<
" [right "
<<
link1
<<
"]"
;
out
<<
" [up "
<<
hex
<<
node
.
m_link
[
2
]
<<
"]"
;
out
<<
" [up "
<<
link2
<<
"]"
;
out
<<
" [side "
<<
dec
<<
node
.
m_side
<<
"]"
;
out
<<
" [side "
<<
dec
<<
node
.
m_side
<<
"]"
;
out
<<
" [occup "
<<
dec
<<
node
.
m_occup
<<
"]"
;
out
<<
" [occup "
<<
dec
<<
node
.
m_occup
<<
"]"
;
out
<<
" [balance "
<<
dec
<<
(
int
)
node
.
m_balance
<<
"]"
;
out
<<
" [balance "
<<
dec
<<
(
int
)
node
.
m_balance
<<
"]"
;
...
@@ -238,7 +253,7 @@ NdbOut&
...
@@ -238,7 +253,7 @@ NdbOut&
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TreePos
&
pos
)
operator
<<
(
NdbOut
&
out
,
const
Dbtux
::
TreePos
&
pos
)
{
{
out
<<
"[TreePos "
<<
hex
<<
&
pos
;
out
<<
"[TreePos "
<<
hex
<<
&
pos
;
out
<<
" [
addr "
<<
hex
<<
pos
.
m_addr
<<
"]"
;
out
<<
" [
loc "
<<
pos
.
m_loc
<<
"]"
;
out
<<
" [pos "
<<
dec
<<
pos
.
m_pos
<<
"]"
;
out
<<
" [pos "
<<
dec
<<
pos
.
m_pos
<<
"]"
;
out
<<
" [match "
<<
dec
<<
pos
.
m_match
<<
"]"
;
out
<<
" [match "
<<
dec
<<
pos
.
m_match
<<
"]"
;
out
<<
" [dir "
<<
dec
<<
pos
.
m_dir
<<
"]"
;
out
<<
" [dir "
<<
dec
<<
pos
.
m_dir
<<
"]"
;
...
@@ -338,7 +353,7 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
...
@@ -338,7 +353,7 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
const
Dbtux
::
Frag
&
frag
=
node
.
m_frag
;
const
Dbtux
::
Frag
&
frag
=
node
.
m_frag
;
const
Dbtux
::
TreeHead
&
tree
=
frag
.
m_tree
;
const
Dbtux
::
TreeHead
&
tree
=
frag
.
m_tree
;
out
<<
"[NodeHandle "
<<
hex
<<
&
node
;
out
<<
"[NodeHandle "
<<
hex
<<
&
node
;
out
<<
" [
addr "
<<
hex
<<
node
.
m_addr
<<
"]"
;
out
<<
" [
loc "
<<
node
.
m_loc
<<
"]"
;
out
<<
" [acc "
<<
dec
<<
node
.
m_acc
<<
"]"
;
out
<<
" [acc "
<<
dec
<<
node
.
m_acc
<<
"]"
;
out
<<
" [flags "
<<
hex
<<
node
.
m_flags
<<
"]"
;
out
<<
" [flags "
<<
hex
<<
node
.
m_flags
<<
"]"
;
out
<<
" [node "
<<
*
node
.
m_node
<<
"]"
;
out
<<
" [node "
<<
*
node
.
m_node
<<
"]"
;
...
...
ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
View file @
eec2835d
...
@@ -285,8 +285,8 @@ Dbtux::tupStoreTh(Signal* signal, const Frag& frag, NodeHandlePtr nodePtr, Store
...
@@ -285,8 +285,8 @@ Dbtux::tupStoreTh(Signal* signal, const Frag& frag, NodeHandlePtr nodePtr, Store
req
->
tableId
=
frag
.
m_indexId
;
req
->
tableId
=
frag
.
m_indexId
;
req
->
fragId
=
frag
.
m_fragId
;
req
->
fragId
=
frag
.
m_fragId
;
req
->
fragPtrI
=
frag
.
m_tupIndexFragPtrI
;
req
->
fragPtrI
=
frag
.
m_tupIndexFragPtrI
;
req
->
tupAddr
=
nodePtr
.
p
->
m_addr
;
req
->
tupAddr
=
RNIL
;
// no longer used
req
->
tupVersion
=
0
;
req
->
tupVersion
=
0
;
// no longer used
req
->
pageId
=
nodePtr
.
p
->
m_loc
.
m_pageId
;
req
->
pageId
=
nodePtr
.
p
->
m_loc
.
m_pageId
;
req
->
pageOffset
=
nodePtr
.
p
->
m_loc
.
m_pageOffset
;
req
->
pageOffset
=
nodePtr
.
p
->
m_loc
.
m_pageOffset
;
req
->
bufferId
=
0
;
req
->
bufferId
=
0
;
...
@@ -346,21 +346,18 @@ Dbtux::tupStoreTh(Signal* signal, const Frag& frag, NodeHandlePtr nodePtr, Store
...
@@ -346,21 +346,18 @@ Dbtux::tupStoreTh(Signal* signal, const Frag& frag, NodeHandlePtr nodePtr, Store
const
Uint32
*
src
=
(
const
Uint32
*
)
buffer
+
storePar
.
m_offset
;
const
Uint32
*
src
=
(
const
Uint32
*
)
buffer
+
storePar
.
m_offset
;
memcpy
(
dst
,
src
,
storePar
.
m_size
<<
2
);
memcpy
(
dst
,
src
,
storePar
.
m_size
<<
2
);
}
}
// fallthru
break
;
case
TupStoreTh
:
:
OpInsert
:
case
TupStoreTh
:
:
OpInsert
:
jam
();
jam
();
// fallthru
case
TupStoreTh
:
:
OpUpdate
:
jam
();
nodePtr
.
p
->
m_addr
=
req
->
tupAddr
;
nodePtr
.
p
->
m_loc
.
m_pageId
=
req
->
pageId
;
nodePtr
.
p
->
m_loc
.
m_pageId
=
req
->
pageId
;
nodePtr
.
p
->
m_loc
.
m_pageOffset
=
req
->
pageOffset
;
nodePtr
.
p
->
m_loc
.
m_pageOffset
=
req
->
pageOffset
;
break
;
break
;
case
TupStoreTh
:
:
OpUpdate
:
jam
();
break
;
case
TupStoreTh
:
:
OpDelete
:
case
TupStoreTh
:
:
OpDelete
:
jam
();
jam
();
nodePtr
.
p
->
m_addr
=
NullTupAddr
;
nodePtr
.
p
->
m_loc
=
NullTupLoc
;
nodePtr
.
p
->
m_loc
.
m_pageId
=
RNIL
;
nodePtr
.
p
->
m_loc
.
m_pageOffset
=
0
;
break
;
break
;
default:
default:
ndbrequire
(
false
);
ndbrequire
(
false
);
...
...
ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
View file @
eec2835d
...
@@ -202,6 +202,7 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
...
@@ -202,6 +202,7 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
jam
();
jam
();
// initialize tree header
// initialize tree header
TreeHead
&
tree
=
fragPtr
.
p
->
m_tree
;
TreeHead
&
tree
=
fragPtr
.
p
->
m_tree
;
new
(
&
tree
)
TreeHead
();
// make these configurable later
// make these configurable later
tree
.
m_nodeSize
=
MAX_TTREE_NODE_SIZE
;
tree
.
m_nodeSize
=
MAX_TTREE_NODE_SIZE
;
tree
.
m_prefSize
=
MAX_TTREE_PREF_SIZE
;
tree
.
m_prefSize
=
MAX_TTREE_PREF_SIZE
;
...
@@ -227,8 +228,8 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
...
@@ -227,8 +228,8 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
break
;
break
;
}
}
tree
.
m_minOccup
=
tree
.
m_maxOccup
-
maxSlack
;
tree
.
m_minOccup
=
tree
.
m_maxOccup
-
maxSlack
;
// root node does not exist
// root node does not exist
(also set by ctor)
tree
.
m_root
=
NullTup
Addr
;
tree
.
m_root
=
NullTup
Loc
;
// fragment is defined
// fragment is defined
c_fragOpPool
.
release
(
fragOpPtr
);
c_fragOpPool
.
release
(
fragOpPtr
);
}
}
...
...
ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp
View file @
eec2835d
...
@@ -80,14 +80,14 @@ Dbtux::preallocNode(Signal* signal, Frag& frag, Uint32& errorCode)
...
@@ -80,14 +80,14 @@ Dbtux::preallocNode(Signal* signal, Frag& frag, Uint32& errorCode)
* Find node in the cache. XXX too slow, use direct links instead
* Find node in the cache. XXX too slow, use direct links instead
*/
*/
void
void
Dbtux
::
findNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
Tup
Addr
addr
)
Dbtux
::
findNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
Tup
Loc
loc
)
{
{
NodeHandlePtr
tmpPtr
;
NodeHandlePtr
tmpPtr
;
tmpPtr
.
i
=
frag
.
m_nodeList
;
tmpPtr
.
i
=
frag
.
m_nodeList
;
while
(
tmpPtr
.
i
!=
RNIL
)
{
while
(
tmpPtr
.
i
!=
RNIL
)
{
jam
();
jam
();
c_nodeHandlePool
.
getPtr
(
tmpPtr
);
c_nodeHandlePool
.
getPtr
(
tmpPtr
);
if
(
tmpPtr
.
p
->
m_
addr
==
addr
)
{
if
(
tmpPtr
.
p
->
m_
loc
==
loc
)
{
jam
();
jam
();
nodePtr
=
tmpPtr
;
nodePtr
=
tmpPtr
;
return
;
return
;
...
@@ -102,18 +102,18 @@ Dbtux::findNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, TupAddr addr
...
@@ -102,18 +102,18 @@ Dbtux::findNode(Signal* signal, Frag& frag, NodeHandlePtr& nodePtr, TupAddr addr
* Get handle for existing node.
* Get handle for existing node.
*/
*/
void
void
Dbtux
::
selectNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
Tup
Addr
addr
,
AccSize
acc
)
Dbtux
::
selectNode
(
Signal
*
signal
,
Frag
&
frag
,
NodeHandlePtr
&
nodePtr
,
Tup
Loc
loc
,
AccSize
acc
)
{
{
ndbrequire
(
addr
!=
NullTupAddr
&&
acc
>
AccNone
);
ndbrequire
(
loc
!=
NullTupLoc
&&
acc
>
AccNone
);
NodeHandlePtr
tmpPtr
;
NodeHandlePtr
tmpPtr
;
// search in cache
// search in cache
findNode
(
signal
,
frag
,
tmpPtr
,
addr
);
findNode
(
signal
,
frag
,
tmpPtr
,
loc
);
if
(
tmpPtr
.
i
==
RNIL
)
{
if
(
tmpPtr
.
i
==
RNIL
)
{
jam
();
jam
();
// add new node
// add new node
seizeNode
(
signal
,
frag
,
tmpPtr
);
seizeNode
(
signal
,
frag
,
tmpPtr
);
ndbrequire
(
tmpPtr
.
i
!=
RNIL
);
ndbrequire
(
tmpPtr
.
i
!=
RNIL
);
tmpPtr
.
p
->
m_
addr
=
addr
;
tmpPtr
.
p
->
m_
loc
=
loc
;
}
}
if
(
tmpPtr
.
p
->
m_acc
<
acc
)
{
if
(
tmpPtr
.
p
->
m_acc
<
acc
)
{
jam
();
jam
();
...
@@ -276,7 +276,7 @@ Dbtux::NodeHandle::pushUp(Signal* signal, unsigned pos, const TreeEnt& ent)
...
@@ -276,7 +276,7 @@ Dbtux::NodeHandle::pushUp(Signal* signal, unsigned pos, const TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
if
(
scanPos
.
m_pos
>=
pos
)
{
if
(
scanPos
.
m_pos
>=
pos
)
{
jam
();
jam
();
#ifdef VM_TRACE
#ifdef VM_TRACE
...
@@ -329,7 +329,7 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
...
@@ -329,7 +329,7 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
const
Uint32
nextPtrI
=
scanPtr
.
p
->
m_nodeScan
;
const
Uint32
nextPtrI
=
scanPtr
.
p
->
m_nodeScan
;
if
(
scanPos
.
m_pos
==
pos
)
{
if
(
scanPos
.
m_pos
==
pos
)
{
jam
();
jam
();
...
@@ -349,7 +349,7 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
...
@@ -349,7 +349,7 @@ Dbtux::NodeHandle::popDown(Signal* signal, unsigned pos, TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_pos
!=
pos
);
ndbrequire
(
scanPos
.
m_pos
!=
pos
);
if
(
scanPos
.
m_pos
>
pos
)
{
if
(
scanPos
.
m_pos
>
pos
)
{
jam
();
jam
();
...
@@ -403,7 +403,7 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
...
@@ -403,7 +403,7 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
const
Uint32
nextPtrI
=
scanPtr
.
p
->
m_nodeScan
;
const
Uint32
nextPtrI
=
scanPtr
.
p
->
m_nodeScan
;
if
(
scanPos
.
m_pos
==
0
)
{
if
(
scanPos
.
m_pos
==
0
)
{
jam
();
jam
();
...
@@ -424,7 +424,7 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
...
@@ -424,7 +424,7 @@ Dbtux::NodeHandle::pushDown(Signal* signal, unsigned pos, TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_pos
!=
0
);
ndbrequire
(
scanPos
.
m_pos
!=
0
);
if
(
scanPos
.
m_pos
<=
pos
)
{
if
(
scanPos
.
m_pos
<=
pos
)
{
jam
();
jam
();
...
@@ -480,7 +480,7 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
...
@@ -480,7 +480,7 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
const
Uint32
nextPtrI
=
scanPtr
.
p
->
m_nodeScan
;
const
Uint32
nextPtrI
=
scanPtr
.
p
->
m_nodeScan
;
if
(
scanPos
.
m_pos
==
pos
)
{
if
(
scanPos
.
m_pos
==
pos
)
{
jam
();
jam
();
...
@@ -501,7 +501,7 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
...
@@ -501,7 +501,7 @@ Dbtux::NodeHandle::popUp(Signal* signal, unsigned pos, TreeEnt& ent)
jam
();
jam
();
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
m_tux
.
c_scanOpPool
.
getPtr
(
scanPtr
);
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
TreePos
&
scanPos
=
scanPtr
.
p
->
m_scanPos
;
ndbrequire
(
scanPos
.
m_
addr
==
m_addr
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_
loc
==
m_loc
&&
scanPos
.
m_pos
<
occup
);
ndbrequire
(
scanPos
.
m_pos
!=
pos
);
ndbrequire
(
scanPos
.
m_pos
!=
pos
);
if
(
scanPos
.
m_pos
<
pos
)
{
if
(
scanPos
.
m_pos
<
pos
)
{
jam
();
jam
();
...
...
ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
View file @
eec2835d
...
@@ -47,7 +47,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
...
@@ -47,7 +47,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
ndbrequire
(
frag
.
m_fragId
<
(
1
<<
frag
.
m_fragOff
));
ndbrequire
(
frag
.
m_fragId
<
(
1
<<
frag
.
m_fragOff
));
TreeHead
&
tree
=
frag
.
m_tree
;
TreeHead
&
tree
=
frag
.
m_tree
;
// check for empty fragment
// check for empty fragment
if
(
tree
.
m_root
==
NullTup
Addr
)
{
if
(
tree
.
m_root
==
NullTup
Loc
)
{
jam
();
jam
();
AccScanConf
*
const
conf
=
(
AccScanConf
*
)
signal
->
getDataPtrSend
();
AccScanConf
*
const
conf
=
(
AccScanConf
*
)
signal
->
getDataPtrSend
();
conf
->
scanPtr
=
req
->
senderData
;
conf
->
scanPtr
=
req
->
senderData
;
...
@@ -275,13 +275,13 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
...
@@ -275,13 +275,13 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
case
NextScanReq
:
:
ZSCAN_CLOSE
:
case
NextScanReq
:
:
ZSCAN_CLOSE
:
jam
();
jam
();
// unlink from tree node first to avoid state changes
// unlink from tree node first to avoid state changes
if
(
scan
.
m_scanPos
.
m_
addr
!=
NullTupAddr
)
{
if
(
scan
.
m_scanPos
.
m_
loc
!=
NullTupLoc
)
{
jam
();
jam
();
const
Tup
Addr
addr
=
scan
.
m_scanPos
.
m_addr
;
const
Tup
Loc
loc
=
scan
.
m_scanPos
.
m_loc
;
NodeHandlePtr
nodePtr
;
NodeHandlePtr
nodePtr
;
selectNode
(
signal
,
frag
,
nodePtr
,
addr
,
AccHead
);
selectNode
(
signal
,
frag
,
nodePtr
,
loc
,
AccHead
);
nodePtr
.
p
->
unlinkScan
(
scanPtr
);
nodePtr
.
p
->
unlinkScan
(
scanPtr
);
scan
.
m_scanPos
.
m_
addr
=
NullTupAddr
;
scan
.
m_scanPos
.
m_
loc
=
NullTupLoc
;
}
}
if
(
scan
.
m_lockwait
)
{
if
(
scan
.
m_lockwait
)
{
jam
();
jam
();
...
@@ -699,14 +699,14 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
...
@@ -699,14 +699,14 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
ScanOp
&
scan
=
*
scanPtr
.
p
;
ScanOp
&
scan
=
*
scanPtr
.
p
;
Frag
&
frag
=
*
c_fragPool
.
getPtr
(
scan
.
m_fragPtrI
);
Frag
&
frag
=
*
c_fragPool
.
getPtr
(
scan
.
m_fragPtrI
);
TreeHead
&
tree
=
frag
.
m_tree
;
TreeHead
&
tree
=
frag
.
m_tree
;
if
(
tree
.
m_root
==
NullTup
Addr
)
{
if
(
tree
.
m_root
==
NullTup
Loc
)
{
// tree may have become empty
// tree may have become empty
jam
();
jam
();
scan
.
m_state
=
ScanOp
::
Last
;
scan
.
m_state
=
ScanOp
::
Last
;
return
;
return
;
}
}
TreePos
pos
;
TreePos
pos
;
pos
.
m_
addr
=
tree
.
m_root
;
pos
.
m_
loc
=
tree
.
m_root
;
NodeHandlePtr
nodePtr
;
NodeHandlePtr
nodePtr
;
// unpack lower bound
// unpack lower bound
const
ScanBound
&
bound
=
*
scan
.
m_bound
[
0
];
const
ScanBound
&
bound
=
*
scan
.
m_bound
[
0
];
...
@@ -724,7 +724,7 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
...
@@ -724,7 +724,7 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
boundPar
.
m_dir
=
0
;
boundPar
.
m_dir
=
0
;
loop:
{
loop:
{
jam
();
jam
();
selectNode
(
signal
,
frag
,
nodePtr
,
pos
.
m_
addr
,
AccPref
);
selectNode
(
signal
,
frag
,
nodePtr
,
pos
.
m_
loc
,
AccPref
);
const
unsigned
occup
=
nodePtr
.
p
->
getOccup
();
const
unsigned
occup
=
nodePtr
.
p
->
getOccup
();
ndbrequire
(
occup
!=
0
);
ndbrequire
(
occup
!=
0
);
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<=
1
;
i
++
)
{
...
@@ -750,11 +750,11 @@ loop: {
...
@@ -750,11 +750,11 @@ loop: {
}
}
if
(
i
==
0
&&
ret
<
0
)
{
if
(
i
==
0
&&
ret
<
0
)
{
jam
();
jam
();
const
Tup
Addr
tupAddr
=
nodePtr
.
p
->
getLink
(
i
);
const
Tup
Loc
loc
=
nodePtr
.
p
->
getLink
(
i
);
if
(
tupAddr
!=
NullTupAddr
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
// continue to left subtree
// continue to left subtree
pos
.
m_
addr
=
tupAddr
;
pos
.
m_
loc
=
loc
;
goto
loop
;
goto
loop
;
}
}
// start scanning this node
// start scanning this node
...
@@ -768,11 +768,11 @@ loop: {
...
@@ -768,11 +768,11 @@ loop: {
}
}
if
(
i
==
1
&&
ret
>
0
)
{
if
(
i
==
1
&&
ret
>
0
)
{
jam
();
jam
();
const
Tup
Addr
tupAddr
=
nodePtr
.
p
->
getLink
(
i
);
const
Tup
Loc
loc
=
nodePtr
.
p
->
getLink
(
i
);
if
(
tupAddr
!=
NullTupAddr
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
// continue to right subtree
// continue to right subtree
pos
.
m_
addr
=
tupAddr
;
pos
.
m_
loc
=
loc
;
goto
loop
;
goto
loop
;
}
}
// start scanning upwards
// start scanning upwards
...
@@ -869,7 +869,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -869,7 +869,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
TreePos
pos
=
scan
.
m_scanPos
;
TreePos
pos
=
scan
.
m_scanPos
;
// get and remember original node
// get and remember original node
NodeHandlePtr
origNodePtr
;
NodeHandlePtr
origNodePtr
;
selectNode
(
signal
,
frag
,
origNodePtr
,
pos
.
m_
addr
,
AccHead
);
selectNode
(
signal
,
frag
,
origNodePtr
,
pos
.
m_
loc
,
AccHead
);
ndbrequire
(
origNodePtr
.
p
->
islinkScan
(
scanPtr
));
ndbrequire
(
origNodePtr
.
p
->
islinkScan
(
scanPtr
));
// current node in loop
// current node in loop
NodeHandlePtr
nodePtr
=
origNodePtr
;
NodeHandlePtr
nodePtr
=
origNodePtr
;
...
@@ -878,21 +878,21 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -878,21 +878,21 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if
(
pos
.
m_dir
==
2
)
{
if
(
pos
.
m_dir
==
2
)
{
// coming up from root ends the scan
// coming up from root ends the scan
jam
();
jam
();
pos
.
m_
addr
=
NullTupAddr
;
pos
.
m_
loc
=
NullTupLoc
;
scan
.
m_state
=
ScanOp
::
Last
;
scan
.
m_state
=
ScanOp
::
Last
;
break
;
break
;
}
}
if
(
nodePtr
.
p
->
m_
addr
!=
pos
.
m_addr
)
{
if
(
nodePtr
.
p
->
m_
loc
!=
pos
.
m_loc
)
{
jam
();
jam
();
selectNode
(
signal
,
frag
,
nodePtr
,
pos
.
m_
addr
,
AccHead
);
selectNode
(
signal
,
frag
,
nodePtr
,
pos
.
m_
loc
,
AccHead
);
}
}
if
(
pos
.
m_dir
==
4
)
{
if
(
pos
.
m_dir
==
4
)
{
// coming down from parent proceed to left child
// coming down from parent proceed to left child
jam
();
jam
();
Tup
Addr
addr
=
nodePtr
.
p
->
getLink
(
0
);
Tup
Loc
loc
=
nodePtr
.
p
->
getLink
(
0
);
if
(
addr
!=
NullTupAddr
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
pos
.
m_
addr
=
addr
;
pos
.
m_
loc
=
loc
;
pos
.
m_dir
=
4
;
// unchanged
pos
.
m_dir
=
4
;
// unchanged
continue
;
continue
;
}
}
...
@@ -937,7 +937,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -937,7 +937,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
jam
();
jam
();
// hit upper bound of single range scan
// hit upper bound of single range scan
pos
.
m_
addr
=
NullTupAddr
;
pos
.
m_
loc
=
NullTupLoc
;
scan
.
m_state
=
ScanOp
::
Last
;
scan
.
m_state
=
ScanOp
::
Last
;
break
;
break
;
}
}
...
@@ -951,10 +951,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -951,10 +951,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
break
;
break
;
}
}
// after node proceed to right child
// after node proceed to right child
Tup
Addr
addr
=
nodePtr
.
p
->
getLink
(
1
);
Tup
Loc
loc
=
nodePtr
.
p
->
getLink
(
1
);
if
(
addr
!=
NullTupAddr
)
{
if
(
loc
!=
NullTupLoc
)
{
jam
();
jam
();
pos
.
m_
addr
=
addr
;
pos
.
m_
loc
=
loc
;
pos
.
m_dir
=
4
;
pos
.
m_dir
=
4
;
continue
;
continue
;
}
}
...
@@ -964,7 +964,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -964,7 +964,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
if
(
pos
.
m_dir
==
1
)
{
if
(
pos
.
m_dir
==
1
)
{
// coming from right child proceed to parent
// coming from right child proceed to parent
jam
();
jam
();
pos
.
m_
addr
=
nodePtr
.
p
->
getLink
(
2
);
pos
.
m_
loc
=
nodePtr
.
p
->
getLink
(
2
);
pos
.
m_dir
=
nodePtr
.
p
->
getSide
();
pos
.
m_dir
=
nodePtr
.
p
->
getSide
();
continue
;
continue
;
}
}
...
@@ -974,7 +974,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -974,7 +974,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
scan
.
m_scanPos
=
pos
;
scan
.
m_scanPos
=
pos
;
// relink
// relink
if
(
scan
.
m_state
==
ScanOp
::
Current
)
{
if
(
scan
.
m_state
==
ScanOp
::
Current
)
{
ndbrequire
(
pos
.
m_
addr
==
nodePtr
.
p
->
m_addr
);
ndbrequire
(
pos
.
m_
loc
==
nodePtr
.
p
->
m_loc
);
if
(
origNodePtr
.
i
!=
nodePtr
.
i
)
{
if
(
origNodePtr
.
i
!=
nodePtr
.
i
)
{
jam
();
jam
();
origNodePtr
.
p
->
unlinkScan
(
scanPtr
);
origNodePtr
.
p
->
unlinkScan
(
scanPtr
);
...
@@ -982,7 +982,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
...
@@ -982,7 +982,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
}
}
}
else
if
(
scan
.
m_state
==
ScanOp
::
Last
)
{
}
else
if
(
scan
.
m_state
==
ScanOp
::
Last
)
{
jam
();
jam
();
ndbrequire
(
pos
.
m_
addr
==
NullTupAddr
);
ndbrequire
(
pos
.
m_
loc
==
NullTupLoc
);
origNodePtr
.
p
->
unlinkScan
(
scanPtr
);
origNodePtr
.
p
->
unlinkScan
(
scanPtr
);
}
else
{
}
else
{
ndbrequire
(
false
);
ndbrequire
(
false
);
...
...
ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp
View file @
eec2835d
This diff is collapsed.
Click to expand it.
ndb/src/kernel/blocks/dbtux/Times.txt
View file @
eec2835d
index maintenance overhead
==========================
"mc02" 2x1700 MHz linux-2.4.9 gcc-2.96 -O3 one db-node
"mc02" 2x1700 MHz linux-2.4.9 gcc-2.96 -O3 one db-node
case a: index on Unsigned
case a: index on Unsigned
...
@@ -6,8 +9,8 @@ testOIBasic -case u -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -
...
@@ -6,8 +9,8 @@ testOIBasic -case u -table 1 -index 1 -fragtype small -threads 10 -rows 100000 -
case b: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned
case b: index on Varchar(5) + Varchar(5) + Varchar(20) + Unsigned
testOIBasic -case u -table 2 -index 4 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
testOIBasic -case u -table 2 -index 4 -fragtype small -threads 10 -rows 100000 -subloop 1 -nologging
update without index,
update with index
1 million rows, pk update without index, pk
update with index
shows ms / 1000 for each and pct overhead
shows ms / 1000
rows
for each and pct overhead
040616 mc02/a 40 ms 87 ms 114 pct
040616 mc02/a 40 ms 87 ms 114 pct
mc02/b 51 ms 128 ms 148 pct
mc02/b 51 ms 128 ms 148 pct
...
@@ -15,4 +18,8 @@ shows ms / 1000 for each and pct overhead
...
@@ -15,4 +18,8 @@ shows ms / 1000 for each and pct overhead
optim 1 mc02/a 38 ms 85 ms 124 pct
optim 1 mc02/a 38 ms 85 ms 124 pct
mc02/b 51 ms 123 ms 140 pct
mc02/b 51 ms 123 ms 140 pct
optim 2 mc02/a 41 ms 80 ms 96 pct
mc02/b 51 ms 117 ms 128 pct
vim: set et:
vim: set et:
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment