Intro
This article is about how to make you API work really faster (i've got 250 times faster) using our library, we are going to show it with our well-known example of Weather Control REST API. But in particular, we consider Create
and Update
operations of a standard CRUD
controls. We made previously mentioned library to reduce amount of code and make a result of the same wrapping DTO (standartize the data contract). Today, we need just only < 10 lines of code to create any controller with all standard CRUD methods.
How we could speed up REST API
We could make API to perform faster if we are going to create/update multiple objects at once (bulk api), sometimes it is possible and could be crucial to achieve a higher performance. In the mentioned above example, we are using Controller class with Bulk Api (derives from BasicBulkCrudController
) could be easily created as follows:
namespace Wissance.WeatherControl.WebApi.Controllers
{
public class MeasurementsSeriesController: BasicBulkCrudController<MeasurementsDto, MeasurementsEntity, int>
{
public MeasurementsSeriesController(MeasurementsManager manager)
{
Manager = manager; // this is for basic operations
_manager = manager; // this for extended operations
}
private MeasurementsManager _manager;
}
}
This code automatically contains 4 mehods:
-
GET /api/MeasurementsSeries
for getting multiple measurements with paging -
GET /api/MeasurementsSeries/{id}
to get one measurements by id -
POST /api/bulk/MeasurementsSeries
for creating multiple objects (bulk API); -
PUT /api/bulk/MeasurementsSeries
for updating multiple objects (bulk API); -
DELETE /api/bulk/MeasurementsSeries/{idList}
for removing multiple object (bulk API), could be called like~/api/bulk/MeasurementsSeries/id=1&id=2&id=5
A full example of Manager class with all bulk operations you could see here. Here i show non-optimal but working example with EntityFramework, even this impl make my code working 250 times faster for creating 10 items (see performance check below method code). So i just add array of MeasurementsEntity and add them to DbSet and after all make one Save instead of multiple for each object:
public override async Task<OperationResultDto<MeasurementsDto[]>> BulkCreateAsync(MeasurementsDto[] data)
{
try
{
IList<MeasurementsEntity> measurements = data.Select(d => MeasurementsFactory.Create(d)).ToList();
await _modelContext.Measurements.AddRangeAsync(measurements);
int result = await _modelContext.SaveChangesAsync();
if (result >= 0)
{
return new OperationResultDto<MeasurementsDto[]>(true, (int)HttpStatusCode.Created, null,
measurements.Select(m => MeasurementsFactory.Create(m)).ToArray());
}
return new OperationResultDto<MeasurementsDto[]>(false, (int)HttpStatusCode.InternalServerError, "An unknown error occurred during measurements creation", null);
}
catch (Exception e)
{
return new OperationResultDto<MeasurementsDto[]>(false, (int)HttpStatusCode.InternalServerError,
$"An error occurred during measurements update: {e.Message}", null);
}
}
Because we claim that we made our API working faster, let’s check performance using Python. For a very rough view we made comparison of time elapse for query single bulk endpoint vs sequential call of non-bulk endpoint (worst case) for POST new items as a result we’got ~250x time performance raise (see Python test here), see picture below
I wrote simple tests using Python that shows following results:
Elapsed time in Non-Bulk REST API with EF is 0.9759984016418457 secs.
Elapsed time in Bulk API with EF is 0.004002094268798828 secs.
So just using such a simple technique we made API working faster in a better case (for non-bulk API example) all request could be made parallel in time, but this isn’t solving bottleneck issue with persistence manager (EntityFramework in this current case).
Conclusion
Therefore, we could conclude that REST resources that allow to use bulk operations could be made working faster, and we have prepared boilerplate reusable solution (Wissance.WebApiToolkit). We would be very appreciated if you could give us a star on Github.
Top comments (0)