Slow send message to SQS using Lambda with low memory - performance

We have created some sample lambdas to test SQS insertion performance.
At first we used 128MB lambdas and got 40ms average for insertions of 7KBytes packages.
When we upgraded the lambda to 256MB we got 20ms averages and when we upgraded to 512MB we even got 11ms average time for insertion.
We wanted to know why the bigger memory/cpu of the lambda gets better insertion speeds on SQS, because we thought sqs insertion should not be related to memory or CPU capacity. In summary: Is there any operation inside the sqs client send operation that requires good CPU/Memory to perform better?
Thanks!
Here is our test code:
public class Function
{
public async Task<string> FunctionHandler(ILambdaContext context)
{
var client = new AmazonSQSClient();
var request = new SendMessageRequest
{
MessageAttributes = new Dictionary<string, MessageAttributeValue>(),
MessageBody = "7kbyte String here...",
QueueUrl = "https://our_account/sqs-test-queue "
};
//Just desconsidering the first 2 sent messages, to desconsider the initial connection overhead
var elapsed00 = await SendMessageResponse(client, request, -2);
var elapsed0 = await SendMessageResponse(client, request, -1);
double totalTime = 0;
const int totalIterations = 1000;
for (int j = 0; j < totalIterations; j++)
{
var elapsed = await SendMessageResponse(client, request, j);
totalTime += elapsed;
}
Console.WriteLine("$$$$$AVERAGE:" + ((double)(totalTime / totalIterations)));
return "End test";
}
private async Task<long> SendMessageResponse(AmazonSQSClient client, SendMessageRequest request, int i)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var response = await client.SendMessageAsync(request);
stopwatch.Stop();
//Console.WriteLine("&&&#####" + i + "Elapsed ms:" + stopwatch.ElapsedMilliseconds + ". For message ID '" +
// response.MessageId + "':");
i++;
return stopwatch.ElapsedMilliseconds;
}
}

SQS isn't behaving differently in relation to your lambda size, the code which you're running in Lambda is changing it's performance based on the memory/CPU allotted.

Related

gRPC slow serialization on large dataset

I know that google states that protobufs don't support large messages (i.e. greater than 1 MB), but I'm trying to stream a dataset using gRPC that's tens of megabytes, and it seems like some people say it's ok, or at least with some splitting...
However, when I try to send an array this way (repeated uint32), it takes like 20 seconds on the same local machine.
#proto
service PAS {
// analyze single file
rpc getPhotonRecords (PhotonRecordsRequest) returns (PhotonRecordsReply) {}
}
message PhotonRecordsRequest {
string fileName = 1;
}
message PhotonRecordsReply {
repeated uint32 PhotonRecords = 1;
}
where PhotonRecordsReply needs to be ~10 million uint32 in length...
Does anyone have an idea on how to speed this up? Or what technology would be more appropriate?
So I think I've implemented streaming based on comments and answers given, but it still takes the same amount of time:
#proto
service PAS {
// analyze single file
rpc getPhotonRecords (PhotonRecordsRequest) returns (stream PhotonRecordsReply) {}
}
class PAS_GRPC(pas_pb2_grpc.PASServicer):
def getPhotonRecords(self, request: pas_pb2.PhotonRecordsRequest, _context):
raw_data_bytes = flb_tools.read_data_bytes(request.fileName)
data = flb_tools.reshape_flb_data(raw_data_bytes)
index = 0
chunk_size = 1024
len_data = len(data)
while index < len_data:
# last chunk
if index + chunk_size > len_data:
yield pas_pb2.PhotonRecordsReply(PhotonRecords=data[index:])
# all other chunks
else:
yield pas_pb2.PhotonRecordsReply(PhotonRecords=data[index:index + chunk_size])
index += chunk_size
Min repro
Github example
If you changed it over to use streams that should help. It took less than 2 seconds to transfer for me. Note this was without ssl and on localhost. This code I threw together. I did run it and it worked. Not sure what might happen if the file is not a multiple of 4 bytes for example. Also the endian order of bytes read is the default for Java.
I made my 10 meg file like this.
dd if=/dev/random of=my_10mb_file bs=1024 count=10240
Here's the service definition. Only thing I added here was the stream to the response.
service PAS {
// analyze single file
rpc getPhotonRecords (PhotonRecordsRequest) returns (stream PhotonRecordsReply) {}
}
Here's the server implementation.
public class PhotonsServerImpl extends PASImplBase {
#Override
public void getPhotonRecords(PhotonRecordsRequest request, StreamObserver<PhotonRecordsReply> responseObserver) {
log.info("inside getPhotonRecords");
// open the file, I suggest using java.nio API for the fastest read times.
Path file = Paths.get(request.getFileName());
try (FileChannel fileChannel = FileChannel.open(file, StandardOpenOption.READ)) {
int blockSize = 1024 * 4;
ByteBuffer byteBuffer = ByteBuffer.allocate(blockSize);
boolean done = false;
while (!done) {
PhotonRecordsReply.Builder response = PhotonRecordsReply.newBuilder();
// read 1000 ints from the file.
byteBuffer.clear();
int read = fileChannel.read(byteBuffer);
if (read < blockSize) {
done = true;
}
// write to the response.
byteBuffer.flip();
for (int index = 0; index < read / 4; index++) {
response.addPhotonRecords(byteBuffer.getInt());
}
// send the response
responseObserver.onNext(response.build());
}
} catch (Exception e) {
log.error("", e);
responseObserver.onError(
Status.INTERNAL.withDescription(e.getMessage()).asRuntimeException());
}
responseObserver.onCompleted();
log.info("exit getPhotonRecords");
}
}
The client just logs the size of the array received.
public long getPhotonRecords(ManagedChannel channel) {
if (log.isInfoEnabled())
log.info("Enter - getPhotonRecords ");
PASGrpc.PASBlockingStub photonClient = PASGrpc.newBlockingStub(channel);
PhotonRecordsRequest request = PhotonRecordsRequest.newBuilder().setFileName("/udata/jdrummond/logs/my_10mb_file").build();
photonClient.getPhotonRecords(request).forEachRemaining(photonRecordsReply -> {
log.info("got this many photons: {}", photonRecordsReply.getPhotonRecordsCount());
});
return 0;
}

How to get speed of network, whether it is fast or slow in xamarin iOS?

How to get speed of network, whether it is fast or slow in xamarin iOS?
I used NetworkReachability, But it is giving result that url is reachable or not?
I want to get speed of network , fast or poor?` private static NetworkReachability _defaultRouteReachability;
public static event EventHandler ReachabilityChanged;
public static bool IsNetworkAvailable(string url)
{
if (_defaultRouteReachability == null)
{
_defaultRouteReachability = new NetworkReachability(url);
_defaultRouteReachability.SetNotification(OnChange);
_defaultRouteReachability.Schedule(CFRunLoop.Current, CFRunLoop.ModeDefault);
}
NetworkReachabilityFlags flags;
return _defaultRouteReachability.TryGetFlags(out flags) &&
IsReachableWithoutRequiringConnection(flags);
}
private static bool IsReachableWithoutRequiringConnection(NetworkReachabilityFlags flags)
{
// Is it reachable with the current network configuration?
bool isReachable = (flags & NetworkReachabilityFlags.Reachable) != 0;
// Do we need a connection to reach it?
bool noConnectionRequired = (flags & NetworkReachabilityFlags.ConnectionRequired) == 0;
// Since the network stack will automatically try to get the WAN up,
// probe that
if ((flags & NetworkReachabilityFlags.IsWWAN) != 0)
noConnectionRequired = true;
return isReachable && noConnectionRequired;
}
private static void OnChange(NetworkReachabilityFlags flags)
{
var h = ReachabilityChanged;
if (h != null)
h(null, EventArgs.Empty);
}`
Something like this can help you, unless you want to use a library. This basically gives you the technical definition of internet speed, but the real number will be a little bigger. It's very similar to the solution suggested by #Martheen
public async Task<string> CheckInternetSpeed()
{
//DateTime Variable To Store Download Start Time.
DateTime dt1 = DateTime.Now;
string internetSpeed;
try
{
// Create Object Of WebClient
var client = new HttpClient();
//Number Of Bytes Downloaded Are Stored In ‘data’
byte[] data = await client.GetByteArrayAsync("https://www.example.com/");
//DateTime Variable To Store Download End Time.
DateTime dt2 = DateTime.Now;
//To Calculate Speed in Kb Divide Value Of data by 1024 And Then by End Time Subtract Start Time To Know Download Per Second.
Console.WriteLine("ConnectionSpeed: DataSize (kb) " + data.Length / 1024);
Console.WriteLine("ConnectionSpeed: ElapsedTime (secs) " + (dt2 - dt1).TotalSeconds);
internetSpeed = "ConnectionSpeed: (kb/s) " + Math.Round((data.Length / 1024) / (dt2 - dt1).TotalSeconds, 2);
}
catch (Exception ex)
{
internetSpeed = "ConnectionSpeed:Unknown Exception-" + ex.Message;
}
Console.WriteLine(internetSpeed);
return internetSpeed;
}
Xamarin Essentials library can't get you Internet speed, but if you use dependency injection, you can use the native api s like this.

Why doesn't Kestrel handle more HTTP connections simultaneously when handlers are slow?

I have a default ASP .NET Core Web API application with a single handler:
[HttpGet("{x}")]
public string Get(string x)
{
var guid = Guid.NewGuid();
var start = DateTime.Now;
Console.WriteLine($"{guid}\t1\tSTRT\t{start}");
var sb = new StringBuilder();
using (var conn = new OracleConnection(CONN_STR)) {
using (var cmd = conn.CreateCommand()) {
conn.Open();
Console.WriteLine($"{guid}\t2\tCONN\t{DateTime.Now - start}");
cmd.CommandText = "select hello4(:x) from dual";
var nameParam = cmd.CreateParameter();
nameParam.ParameterName = "x";
nameParam.Value = x;
cmd.Parameters.Add(nameParam);
var ret = cmd.ExecuteScalar();
if (ret is string xname) {
sb.Append("{\"x\":");
sb.Append(x);
sb.Append("\",\"xname\":\"");
sb.Append(xname);
sb.Append("\"}");
} else {
sb.Append("{\"error\":\"no data found\"}");
}
}
}
Console.WriteLine($"{guid}\t3\tDONE\t{DateTime.Now - start}");
return sb.ToString();
}
I load test it using vegeta: vegeta attack -targets=targets.txt -duration=10s -rate=100 -timeout=0 | vegeta report.
When hello4 is fast, I can see in the stdout that the handler is invoked 100 times per second.
When hello4 contains dbms_lock.sleep(1); to simulate extra processing time, I see that the handler is invoked much fewer times per second, about 20. I actually expected it to still be invoked about 100 times per second, placing extra stress on the DB and exhausting the SGA (my connection pool limit is 1024).
Why doesn't that happen and how can I force it to start handling more incoming connections simultaneously?
Running cmd.ExecuteScalar in a Task was the right idea, but it has to be a long running task to avoid blocking all threads in the application pool:
private static TaskFactory<object> tf = new TaskFactory<object>();
//and in the method
await tf.StartNew((Func<object>)cmd.ExecuteScalar, TaskCreationOptions.LongRunning).ConfigureAwait(false);
This allows Kestrel to keep handling incoming connections at the rate that they arrive.

Calculating Processing and Request time for multiple Asynchronous Requests

For data visualization request in my application, I am sending multiple AJAX requests to a servlet in order to get the data in chunks and on callback of each request, the data received is rendered over map.
For this request, I am trying to calculate:
Request Time (how much total time it took for client to get data from server)
Processing Time (how much total time it took for client to render the data on client side)
In order to do this, I am capturing start time of each request before sending it to server (using jquery "beforeSend") and "onSuccess" event of each request, the end time is captured.
Once the all requests are completed, I am deducting the "start time" of first request from the "end time" of last request in order to calculate the total time the client took for fetching records from server. (Similarly for Processing Time)
But somehow my calculation doesn't produce correct results. Could any one please provide me some suggestions for this issue?
for explaining my question in more better way:
var dataProviderRequestsStartTime = [];
var dataProviderRequestsEndTime = [];
var dataParsingStartTime = [];
var dataParsingEndTime = [];
getResults(ids);
var getResults = function(totalIds) {
for(var i=0; i<10; i++;) {
requestResultForOneChunk(totalIds[i]);
}
};
var requestResultForOneChunk = function(streetIds) {
$.ajax({
beforeSend: function() {
var requestStartTime = new Date().getTime();
dataProviderRequestsStartTime.push(requestStartTime);
},
type : 'POST',
url : "myServlet",
contentType : "application/x-www-form-urlencoded",
data : {
"ids" : streetIds,
},
success : function(response) {
//Request Finished
var dataProvideRequestEndTime = new Date().getTime();
dataProviderRequestsEndTime.push(dataProvideRequestEndTime);
addFeaturesToMap(response);
},
error : function(x, e) {
alert("Something went wrong in the request" + e);
}
});
};
var addFeaturesToMap = function(measurements) {
//Parsing Started
var featureParsingStartTime = new Date().getTime();
dataParsingStartTime.push(featureParsingStartTime);
doParsing(measurements);
//Parsing Finished
featureParsingEndTime = new Date().getTime();
dataParsingEndTime.push(featureParsingEndTime);
};
$("#loading").bind(
"ajaxStart",
function(options) {
ajaxStartTime = options.timeStamp;
}).bind("ajaxStop", function(options) {
var ajaxEndTime = options.timeStamp;
var totalTime = (ajaxEndTime - ajaxStartTime);
calculateTimeBreakDown();
});
var calculateTimeBreakDown = function() {
var totalValues = dataProviderRequestsEndTime.length;
var lastValueIndex = totalValues - 1;
// Request Time calculation
var endTimeOfLastRequest = dataProviderRequestsEndTime[lastValueIndex];
var startTimeOfFirstRequest = dataProviderRequestsStartTime[0];
var totalRequestTime = (endTimeOfLastRequest - startTimeOfFirstRequest);
// Parsing Time Calculation
var endTimeOfLastParsing = dataParsingEndTime[lastValueIndex];
var startTimeOfFirstParsing = dataParsingStartTime[0];
var totalParsingTime = (endTimeOfLastParsing - startTimeOfFirstParsing);
};
Finally, I have requestTime(totalRequestTime) and parsingTime(totalParsingTime). But the problem is adding these both doesn't produce value near to total time which is calculated using ajax start and stop.
look at the .ajaxStart() and .ajaxStop() events for "total time", (<- those are also great for progressbars)
http://api.jquery.com/ajaxStart/
http://api.jquery.com/ajaxStop/
and .ajaxSend() and .ajaxComplete() events for "cumulative time" calculations.
http://api.jquery.com/ajaxSend/
http://api.jquery.com/ajaxComplete/
look at this code:
var totalTime = null;
var cachedTime = null;
function alertLoadingTime() {
if(!totalTime) return;
var loadingTime = totalTime / 1000;
console.log("loaded " + loadingTime + " seconds");
}
function timingStart() {
cachedTime = new Date;
}
function timingEnd() {
var endTime = new Date;
totalTime += endTime - cachedTime;
cachedTime = null;
alertLoadingTime();
}
$(document).ajaxStart(timingStart);
$(document).ajaxStop(timingEnd);
note that it will only account for time spent doing ajax calls and won't include the initial page loading time.
to time the parsing:
use the same functions as before but change totalTime to totalParsingTime. (Note: you can achieve this by changing totalTime to reference some other variable)
Call timingStart() right before you append the result of the ajax call to the dom tree.
Have the server add timingEnd() to the end of every response.
totalTime will then be set to the time it took to add everything to the DOM tree.
solution for you would to rely on jquery ajax callback methods
ajaxStart : Register a handler to be called when the first Ajax request begins.
ajaxStop : Register a handler to be called when all Ajax requests have completed including success and error callbacks
I have used the below code snippet in my application and it works perfectly fine to report page rendering time including ajaxs.
var startTime = 0,endTime = 0;
$(document).ajaxStart(function(){
startTime = new Date();
});
$(document).ajaxStop(function(){
endTime = new Date();
console.log("total time required : ",endTime - startTime); //Total time in milliseconds including time spent in success or error callbacks
});

What is the use of "AsyncPattern" property of "OperationContractAttribute" + wcf?

Thus for used ajax enabled wcf services to get records from DB and display it in client without using AsyncPattern property of OperationContractAttribute....
When should i consider AsyncPattern property?
Sample of my operationcontract methods,
[OperationContract]
public string GetDesignationData()
{
DataSet dt = GetDesignationViewData();
return GetJSONString(dt.Tables[0]);
}
public string GetJSONString(DataTable Dt)
{
string[] StrDc = new string[Dt.Columns.Count];
string HeadStr = string.Empty;
for (int i = 0; i < Dt.Columns.Count; i++)
{
StrDc[i] = Dt.Columns[i].Caption;
HeadStr += "\"" + StrDc[i] + "\" : \"" + StrDc[i] + i.ToString() + "¾" + "\",";
}
HeadStr = HeadStr.Substring(0, HeadStr.Length - 1);
StringBuilder Sb = new StringBuilder();
Sb.Append("{\"" + Dt.TableName + "\" : [");
for (int i = 0; i < Dt.Rows.Count; i++)
{
string TempStr = HeadStr;
Sb.Append("{");
for (int j = 0; j < Dt.Columns.Count; j++)
{
if (Dt.Rows[i][j].ToString().Contains("'") == true)
{
Dt.Rows[i][j] = Dt.Rows[i][j].ToString().Replace("'", "");
}
TempStr = TempStr.Replace(Dt.Columns[j] + j.ToString() + "¾", Dt.Rows[i][j].ToString());
}
Sb.Append(TempStr + "},");
}
Sb = new StringBuilder(Sb.ToString().Substring(0, Sb.ToString().Length - 1));
Sb.Append("]}");
return Sb.ToString();
}
public DataSet GetDesignationViewData()
{
try
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
return SqlHelper.ExecuteDataset(connectionString, CommandType.StoredProcedure, DataTemplate.spDesignation_View);
}
catch (Exception err)
{
throw err;
}
}
AsyncPattern has a few uses- it's mainly a server performance optimization that allows you to free up worker pool request threads on blocking operations. For example, when a long-running blocking operation like DB access occurs, if you're using an async DB API on the server with AsyncPattern, the worker thread can return to the pool and service other requests. The original request is "awakened" later on another worker thread when the DB access completes, and the rest of the work is done (the service client just patiently waits- this is all transparent to it unless you're using an AsyncPattern-aware client and binding). This CAN allow your service to process more requests, if done carefully. To take advantage, you need to be using APIs on the server that have native async implementations. The only one I see that might be a candidate is the DB call that's happening in your SQLHelper.ExecuteDataset method- you'd have to read up on the underlying API to make sure a TRUE asynchronous option is available (presence of BeginXXX/EndXXX methods doesn't necessarily mean it's a TRUE async impl). The System.SqlClient stuff is truly async.
A word of caution: you have to be processing a lot of requests to make this worthwhile- there's a significant cost to code complexity and readability to split things up this way. You also need to understand multi-threaded programming very well- there are numerous pitfalls around locking, error handling, etc, that are well outside the scope of a SO post.
Good luck!

Resources