Skip to content

Commit 675d793

Browse files
liuh-80yxieca
authored andcommitted
Re-write sonic-db-cli with c++ for sonic startup performance issue (#607)
#### Why I did it Fix sonic-db-cli high CPU usage on SONiC startup issue: sonic-net/sonic-buildimage#10218 ETA of this issue will be 2022/05/31 #### How I did it Re-write sonic-cli with c++. #### How to verify it Add c++ unit test to cover all code. Pass all E2E test scenario. #### Which release branch to backport (provide reason below if selected) <!-- - Note we only backport fixes to a release branch, *not* features! - Please also provide a reason for the backporting below. - e.g. - [x] 202006 --> - [ ] 201811 - [ ] 201911 - [ ] 202006 - [ ] 202012 - [ ] 202106 - [ ] 202111 #### Description for the changelog Re-write sonic-cli with c++ for sonic startup performance issue
1 parent 1155773 commit 675d793

17 files changed

+807
-3
lines changed

Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
SUBDIRS = common pyext tests
1+
SUBDIRS = common pyext sonic-db-cli tests
22

33
ACLOCAL_AMFLAGS = -I m4

common/rediscommand.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ void RedisCommand::formatArgv(int argc, const char **argv, const size_t *argvlen
4949
}
5050
}
5151

52+
void RedisCommand::format(const vector<string> &commands)
53+
{
54+
vector<const char*> args;
55+
for (auto& command : commands)
56+
{
57+
args.push_back(command.c_str());
58+
}
59+
formatArgv(static_cast<int>(args.size()), args.data(), NULL);
60+
}
61+
5262
/* Format HMSET key multiple field value command */
5363
void RedisCommand::formatHMSET(const std::string &key,
5464
const std::vector<FieldValueTuple> &values)

common/rediscommand.h

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class RedisCommand {
2525

2626
void format(const char *fmt, ...);
2727
void formatArgv(int argc, const char **argv, const size_t *argvlen);
28+
void format(const std::vector<std::string> &commands);
2829

2930
/* Format HMSET key multiple field value command */
3031
#ifndef SWIG

common/redisreply.cpp

+42-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <stdint.h>
33
#include <vector>
44
#include <iostream>
5+
#include <sstream>
56
#include <system_error>
67
#include <functional>
78

@@ -158,7 +159,7 @@ void RedisReply::checkReplyType(int expectedType)
158159
const char *err = (m_reply->type == REDIS_REPLY_STRING || m_reply->type == REDIS_REPLY_ERROR) ?
159160
m_reply->str : "NON-STRING-REPLY";
160161

161-
string errmsg = "Expected to get redis type " + to_string(expectedType) + " got type " + to_string(m_reply->type) + ", err: " + err;
162+
string errmsg = "Expected to get redis type " + std::to_string(expectedType) + " got type " + std::to_string(m_reply->type) + ", err: " + err;
162163
SWSS_LOG_ERROR("%s", errmsg.c_str());
163164
throw system_error(make_error_code(errc::io_error), errmsg);
164165
}
@@ -225,4 +226,44 @@ template<> RedisMessage RedisReply::getReply<RedisMessage>()
225226
return ret;
226227
}
227228

229+
230+
string RedisReply::to_string()
231+
{
232+
return to_string(getContext());
233+
}
234+
235+
string RedisReply::to_string(redisReply *reply)
236+
{
237+
switch(reply->type)
238+
{
239+
case REDIS_REPLY_INTEGER:
240+
return std::to_string(reply->integer);
241+
242+
case REDIS_REPLY_STRING:
243+
case REDIS_REPLY_ERROR:
244+
case REDIS_REPLY_STATUS:
245+
case REDIS_REPLY_NIL:
246+
return string(reply->str, reply->len);
247+
248+
case REDIS_REPLY_ARRAY:
249+
{
250+
stringstream result;
251+
for (size_t i = 0; i < reply->elements; i++)
252+
{
253+
result << to_string(reply->element[i]);
254+
255+
if (i < reply->elements - 1)
256+
{
257+
result << endl;
258+
}
259+
}
260+
return result.str();
261+
}
262+
263+
default:
264+
SWSS_LOG_ERROR("invalid type %d for message", reply->type);
265+
return string();
266+
}
267+
}
268+
228269
}

common/redisreply.h

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ class RedisReply
9292
/* Check that the status is QUEUED, throw exception otherwise */
9393
void checkStatusQueued();
9494

95+
std::string to_string();
96+
97+
static std::string to_string(redisReply *reply);
98+
9599
private:
96100
void checkStatus(const char *status);
97101
void checkReply();

configure.ac

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ AC_CONFIG_FILES([
9898
pyext/Makefile
9999
pyext/py2/Makefile
100100
pyext/py3/Makefile
101+
sonic-db-cli/Makefile
101102
tests/Makefile
102103
])
103104

debian/control

+6
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,9 @@ Architecture: any
3535
Depends: ${shlibs:Depends}, ${misc:Pre-Depends}
3636
Section: libs
3737
Description: This package contains Switch State Service common Python3 library.
38+
39+
Package: sonic-db-cli
40+
Architecture: any
41+
Depends: ${shlibs:Depends}, ${misc:Pre-Depends}
42+
Section: libs
43+
Description: This package contains SONiC DB cli.

debian/sonic-db-cli.dirs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
usr/bin

debian/sonic-db-cli.install

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
usr/bin/sonic-db-cli

sonic-db-cli/Makefile.am

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
INCLUDES = -I $(top_srcdir)
2+
3+
if DEBUG
4+
DBGFLAGS = -ggdb -DDEBUG
5+
else
6+
DBGFLAGS = -g -DNDEBUG
7+
endif
8+
9+
lib_LTLIBRARIES = libsonicdbcli.la
10+
libsonicdbcli_la_SOURCES = sonic-db-cli.cpp
11+
libsonicdbcli_la_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
12+
libsonicdbcli_la_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
13+
libsonicdbcli_la_LDFLAGS = -L$(top_srcdir)/common -lswsscommon -lpthread
14+
15+
bin_PROGRAMS = sonic-db-cli
16+
sonic_db_cli_SOURCES = sonic-db-cli.cpp main.cpp
17+
sonic_db_cli_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
18+
sonic_db_cli_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
19+
sonic_db_cli_LDFLAGS = -L$(top_srcdir)/common -lswsscommon -lpthread

sonic-db-cli/main.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "sonic-db-cli.h"
2+
#include "common/dbconnector.h"
3+
4+
using namespace swss;
5+
using namespace std;
6+
7+
int main(int argc, char** argv)
8+
{
9+
auto initializeGlobalConfig = []()
10+
{
11+
SonicDBConfig::initializeGlobalConfig(SonicDBConfig::DEFAULT_SONIC_DB_GLOBAL_CONFIG_FILE);
12+
};
13+
14+
auto initializeConfig = []()
15+
{
16+
SonicDBConfig::initialize(SonicDBConfig::DEFAULT_SONIC_DB_CONFIG_FILE);
17+
};
18+
19+
return sonic_db_cli(
20+
argc,
21+
argv,
22+
initializeGlobalConfig,
23+
initializeConfig);
24+
}

0 commit comments

Comments
 (0)