Tampons de protocole: devrais-je utiliser int64 ou fixed64 pour représenter une valeur .NET DateTime?

StackOverflow https://stackoverflow.com/questions/837537

Question

Je dois sérialiser une valeur .NET DateTime dans un message de mémoire tampon de protocole.

Mon plan consiste à utiliser DateTime.ToBinary (), puis à transmettre la valeur renvoyée 64 bits dans le message. Mais je ne sais pas quoi choisir en tant que type de données tampons de protocole pour le représenter.

Je suppose que je suis perplexe à propos de l'utilisation des types de données fixed64 (ou sfixed64).

Dans ce scénario, je suppose que j'utiliserais les types signés car les valeurs renvoyées par DateTime.ToBinary () peuvent être négatives et positives.

Était-ce utile?

La solution

Eh bien, vous voulez absolument que int64 ou sfixed64 gère la valeur en cours de signature.

Après un test rapide, DateTime.Now.ToBinary () est codé sur 10 octets à l'aide de int64 alors que sfixed64 utilisera toujours 8 octets. Fondamentalement, le codage à longueur variable est idéal pour les petits nombres, mais devient plus grand que le codage fixe pour les grands nombres. (C’est le même type de compromis que d’utiliser UTF-8 au lieu de UTF-16 - les caractères ASCII peuvent être codés en UTF-8 en un seul octet, mais les points de code finissent par être codés en tant que 2, puis 3 octets, alors que les caractères UTF -16 utilise toujours 2 octets pour les caractères du BMP.)

Je suppose que les valeurs DateTime.ToBinary () sont susceptibles d'être assez volumineuses (sans connaître les détails de son comportement), donc sfixed64 est plus approprié.

Est-ce que cela a du sens?

Autres conseils

Dans protobuf-net , j'utilise une approche d'échelle graduée (et même , il gère tout cela pour vous si vous utilisez simplement DateTime ) - l’équivalent .proto est quelque chose comme ceci:

message DateTime {
  optional sint64 value = 1; // the offset (in units of the selected scale)
                             // from 1970/01/01
  optional TimeSpanScale scale = 2 [default = DAYS]; // the scale of the
                                                     // timespan
  enum TimeSpanScale {
    DAYS = 0;
    HOURS = 1;
    MINUTES = 2;
    SECONDS = 3;
    MILLISECONDS = 4;

    MINMAX = 15; // dubious
  }
}

i.e. si le DateTime peut être exprimé en jours entiers, j’envoie simplement le nombre de jours depuis 1970, etc. - plus un petit marqueur à l’échelle. Cela signifie que les dates peuvent être envoyées un peu plus efficacement, mais cela ne coûte pas beaucoup plus cher pour les autres échelles.

Personnellement, je n’utiliserais pas ToBinary () - j’utiliserais explicitement le décalage d’une échelle connue depuis une époque connue (telle que l’époque unix). Cela le rend plus portable entre les plates-formes. Mais si vous envoyez (par exemple) uniquement le décalage en millisecondes, une échelle fixe sera généralement plus efficace qu'une échelle de longueur variable. Que vous ayez besoin de signer ou non, cela dépend si vous avez besoin de dates antérieures à votre époque ;-p

Vous devez utiliser un nombre signé de 64 bits, non pas parce que le DateTime peut être négatif, mais parce que la méthode ToBinary renvoie un Int64 . , qui est un nombre signé de 64 bits.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top