Используйте прямые классы в gRPC, чтобы избежать копирования данных - PullRequest
0 голосов
/ 03 января 2019

Мы хотим избежать копирования данных в связи gRPC.

У меня есть следующий (не настоящий) пример в прото-файле:

message Person
{
    string id = 1;
    string Name = 2;
    string Address = 3;
}

message PersonId
{
    required string id = 1;
}

service PersonService
{
    rpc GetPersonById( PersonId ) returns Person;
}

И он отлично работает.Но когда я его реализую, я должен скопировать все свои данные в запрос:

class PersonServiceImpl : PersonService.MaterialServiceBase
{
    public override Task<Person> GetPersonById( PersonId request, ServerCallContext context )
    {
        Datamodel.Person person = GetPersonForDatabaseAsync(request.Id).Result;

        Task.FromResult( new Person() {
            Id = person.Id,
            Name = person.Name,
            Address = person.Address
            } );
    }
}

Но это будет очень здорово, когда мы избегаем копирования данных, потому что это медленно и опасно, когдамы добавляем нового участника в Person.Идеальный код будет следующим:

    public override Task<Person> GetPersonById( PersonId request, ServerCallContext context )
    {
        return GetPersonForDatabaseAsync(request.Id);
    }

Возможно ли это?

Мы проверяем производительность, и 25% времени уходит на маршалинг и демаршалинг, особенно на большой тип, который вложеннапример, огромные заказы.

Я добавляю тег java, потому что это актуальный вопрос и в среде Java.

Редактировать из-за комментария:

namespace Datamodel
{
    class Person
    {
        string Id { get; set; }
        string Name { get; set; }
        string Address { get; set; }
    }
}

Так чтовопрос, с другой точки зрения: как мне изменить Datamodel.Person, чтобы сделать его совместимым с gRPC ответом.

1 Ответ

0 голосов
/ 05 января 2019

К сожалению, это невозможно из-за генерации кода protobuf.Все члены и функции жестко запрограммированы.

Было бы замечательно, когда gRPC дает возможность использовать интерфейс вместо прямого определения члена - класса сообщения.Этот интерфейс будет содержать все члены и функцию создания.

Таким образом, сгенерированный код изменяется с:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom( pb::CodedInputStream input )
{
    uint tag;
    while ( ( tag = input.ReadTag() ) != 0 )
    {
        switch ( tag )
        {
            default:
                _unknownFields = pb::UnknownFieldSet.MergeFieldFrom( _unknownFields, input );
                break;
            case 10:
                {
                    Id = input.ReadString();
                    break;
                }
            case 18:
                {
                    Name = input.ReadString();
                    break;
                }
        }
    }
}

На это:

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom( pb::CodedInputStream input )
{
    uint tag;
    while ( ( tag = input.ReadTag() ) != 0 )
    {
        switch ( tag )
        {
            default:
                Instance.UnknownFields = pb::UnknownFieldSet.MergeFieldFrom( Instance.UnknownFields, input );
                break;
            case 10:
                {
                    Instance.Id = input.ReadString();
                    break;
                }
            case 18:
                {
                    Instance.Name = input.ReadString();
                    break;
                }
        }
    }
}

, где Instance является реализацией создаваемого интерфейсаиз protofile:

public interface IPerson
{
    private pb::UnknownFieldSet UnknownFields;
    string Id { get; set; }
    string Name { get; set; }
}

Если My Datamodel.Person реализует интерфейс, а сгенерированное сообщение Person сохраняет и извлекает данные через этот интерфейс IPerson, тогда мы можем избежать копирования данных и использованияиз gRPC будет быстрее с более 25%.

Я думаю, что это огромное преимущество для gRPC. Может быть, Джон Скит может сделать это.Я могу вносить изменения в c, c ++ и c #, когда у нас есть четкие понятия.

Кстати, это будет огромным шагом вперед для gRPC, потому что это одна из причин, почему люди вместо этого используют RESTэтогоВ мире REST есть возможность извлекать данные непосредственно в Datamodel структуры с помощью JSON Serialize.С помощью Deserialize они могут отправлять непосредственно структуру.

Это должна быть новая опция в файле protobuf, и это возможно на всех языках, поддерживающих интерфейсы.

...