Skip to content

Commit 87aeb07

Browse files
committed
precompute sizes and and simplify BasicProperties presence
1 parent 05d0930 commit 87aeb07

File tree

2 files changed

+94
-71
lines changed

2 files changed

+94
-71
lines changed

projects/Apigen/apigen/Apigen.cs

Lines changed: 81 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -587,43 +587,20 @@ public void EmitClassProperties(AmqpClass c)
587587
}
588588
EmitLine("");
589589
foreach (AmqpField f in c.m_Fields)
590-
{
591-
if (!IsBoolean(f))
592-
{
593-
EmitLine($" private bool _{MangleMethod(f.Name)}_present = false;");
594-
}
595-
}
596-
EmitLine("");
597-
foreach (AmqpField f in c.m_Fields)
598590
{
599591
EmitSpecComment(f.DocumentationComment(" ", "@label"));
600592
EmitLine($" public {maybeOverride}{MapDomain(f.Domain)} {MangleClass(f.Name)}");
601593
EmitLine(" {");
602594
EmitLine($" get => _{MangleMethod(f.Name)};");
603-
EmitLine(" set");
604-
EmitLine(" {");
605-
if (!IsBoolean(f))
606-
{
607-
if (IsReferenceType(f))
608-
{
609-
EmitLine($" _{MangleMethod(f.Name)}_present = value != null;");
610-
611-
}
612-
else
613-
{
614-
EmitLine($" _{MangleMethod(f.Name)}_present = true;");
615-
}
616-
}
617-
EmitLine($" _{MangleMethod(f.Name)} = value;");
618-
EmitLine(" }");
595+
EmitLine($" set => _{MangleMethod(f.Name)} = value;");
619596
EmitLine(" }");
620597
EmitLine("");
621598
}
622599
foreach (AmqpField f in c.m_Fields)
623600
{
624601
if (!IsBoolean(f))
625602
{
626-
EmitLine($" public {maybeOverride}void Clear{MangleClass(f.Name)}() => _{MangleMethod(f.Name)}_present = false;");
603+
EmitLine($" public {maybeOverride}void Clear{MangleClass(f.Name)}() => _{MangleMethod(f.Name)} = default;");
627604
EmitLine("");
628605
}
629606
}
@@ -632,7 +609,7 @@ public void EmitClassProperties(AmqpClass c)
632609
{
633610
if (!IsBoolean(f))
634611
{
635-
EmitLine($" public {maybeOverride}bool Is{MangleClass(f.Name)}Present() => _{MangleMethod(f.Name)}_present;");
612+
EmitLine($" public {maybeOverride}bool Is{MangleClass(f.Name)}Present() => _{MangleMethod(f.Name)} != default;");
636613
EmitLine("");
637614
}
638615
}
@@ -647,19 +624,19 @@ public void EmitClassProperties(AmqpClass c)
647624
{
648625
if (IsBoolean(f))
649626
{
650-
EmitLine($" _{MangleMethod(f.Name)} = reader.ReadBit();");
627+
EmitLine($" var {MangleMethod(f.Name)} = reader.ReadBit();");
651628
}
652629
else
653630
{
654-
EmitLine($" _{MangleMethod(f.Name)}_present = reader.ReadPresence();");
631+
EmitLine($" var {MangleMethod(f.Name)}_present = reader.ReadPresence();");
655632
}
656633
}
657634
EmitLine(" reader.FinishPresence();");
658635
foreach (AmqpField f in c.m_Fields)
659636
{
660637
if (!IsBoolean(f))
661638
{
662-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ _{MangleMethod(f.Name)} = reader.Read{MangleClass(ResolveDomain(f.Domain))}(); }}");
639+
EmitLine($" if ({MangleMethod(f.Name)}_present) {{ _{MangleMethod(f.Name)} = reader.Read{MangleClass(ResolveDomain(f.Domain))}(); }}");
663640
}
664641
}
665642
EmitLine(" }");
@@ -674,58 +651,56 @@ public void EmitClassProperties(AmqpClass c)
674651
}
675652
else
676653
{
677-
EmitLine($" writer.WritePresence(_{MangleMethod(f.Name)}_present);");
654+
EmitLine($" writer.WritePresence(Is{MangleClass(f.Name)}Present());");
678655
}
679656
}
680657
EmitLine(" writer.FinishPresence();");
681658
foreach (AmqpField f in c.m_Fields)
682659
{
683660
if (!IsBoolean(f))
684661
{
685-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ writer.Write{MangleClass(ResolveDomain(f.Domain))}(_{MangleMethod(f.Name)}); }}");
662+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ writer.Write{MangleClass(ResolveDomain(f.Domain))}(_{MangleMethod(f.Name)}); }}");
686663
}
687664
}
688665
EmitLine(" }");
689666
EmitLine("");
690667
EmitLine(" public override int GetRequiredPayloadBufferSize()");
691668
EmitLine(" {");
692-
EmitLine(" int bufferSize = 0;");
693-
EmitLine(" int fieldCount = 0;");
669+
EmitLine($" int bufferSize = {Math.Max((int)Math.Ceiling(c.m_Fields.Count / 15.0), 1) * 2}; // number of presence fields ({c.m_Fields.Count}) in 2 bytes blocks");
694670
foreach (AmqpField f in c.m_Fields)
695671
{
696672
switch (MapDomain(f.Domain))
697673
{
698674
case "byte":
699-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize++; }} // _{MangleMethod(f.Name)} in bytes");
675+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize++; }} // _{MangleMethod(f.Name)} in bytes");
700676
break;
701677
case "string":
702-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize += 1 + Encoding.UTF8.GetByteCount(_{MangleMethod(f.Name)}); }} // _{MangleMethod(f.Name)} in bytes");
678+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize += 1 + Encoding.UTF8.GetByteCount(_{MangleMethod(f.Name)}); }} // _{MangleMethod(f.Name)} in bytes");
703679
break;
704680
case "byte[]":
705-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize += 4 + _{MangleMethod(f.Name)}.Length; }} // _{MangleMethod(f.Name)} in bytes");
681+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize += 4 + _{MangleMethod(f.Name)}.Length; }} // _{MangleMethod(f.Name)} in bytes");
706682
break;
707683
case "ushort":
708-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize += 2; }} // _{MangleMethod(f.Name)} in bytes");
684+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize += 2; }} // _{MangleMethod(f.Name)} in bytes");
709685
break;
710686
case "uint":
711-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize += 4; }} // _{MangleMethod(f.Name)} in bytes");
687+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize += 4; }} // _{MangleMethod(f.Name)} in bytes");
712688
break;
713689
case "ulong":
714690
case "AmqpTimestamp":
715-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize += 8; }} // _{MangleMethod(f.Name)} in bytes");
691+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize += 8; }} // _{MangleMethod(f.Name)} in bytes");
716692
break;
717693
case "bool":
718694
// TODO: implement if used, not used anywhere yet
719695
break;
720696
case "IDictionary<string, object>":
721-
EmitLine($" if (_{MangleMethod(f.Name)}_present) {{ fieldCount++; bufferSize += WireFormatting.GetTableByteCount(_{MangleMethod(f.Name)}); }} // _{MangleMethod(f.Name)} in bytes");
697+
EmitLine($" if (Is{MangleClass(f.Name)}Present()) {{ bufferSize += WireFormatting.GetTableByteCount(_{MangleMethod(f.Name)}); }} // _{MangleMethod(f.Name)} in bytes");
722698
break;
723699
default:
724700
throw new ArgumentOutOfRangeException($"Can't handle size calculations for type = {f.Domain};");
725701
}
726702
}
727703

728-
EmitLine($" bufferSize += Math.Max((int)Math.Ceiling(fieldCount / 15.0), 1) * 2; // number of presence fields in bytes");
729704
EmitLine(" return bufferSize;");
730705
EmitLine(" }");
731706
EmitLine("");
@@ -736,31 +711,23 @@ public void EmitClassProperties(AmqpClass c)
736711
int remaining = c.m_Fields.Count;
737712
foreach (AmqpField f in c.m_Fields)
738713
{
739-
Emit($" sb.Append(\"{f.Name}=\");");
714+
Emit($" sb.Append(\"{f.Name}=\")");
740715
if (IsBoolean(f))
741716
{
742-
Emit($" sb.Append(_{MangleMethod(f.Name)});");
717+
Emit($".Append(_{MangleMethod(f.Name)})");
743718
}
744719
else
745720
{
746-
string x = MangleMethod(f.Name);
747-
if (IsReferenceType(f))
748-
{
749-
Emit($" sb.Append(_{x}_present ? (_{x} == null ? \"(null)\" : _{x}.ToString()) : \"_\");");
750-
}
751-
else
752-
{
753-
Emit($" sb.Append(_{x}_present ? _{x}.ToString() : \"_\");");
754-
}
721+
Emit($".Append(Is{MangleClass(f.Name)}Present() ? _{MangleMethod(f.Name)}.ToString() : \"_\")");
755722
}
756723
remaining--;
757724
if (remaining > 0)
758725
{
759-
EmitLine(" sb.Append(\", \");");
726+
EmitLine(".Append(\", \");");
760727
}
761728
else
762729
{
763-
EmitLine("");
730+
EmitLine(";");
764731
}
765732
}
766733
}
@@ -817,7 +784,6 @@ public void EmitClassMethodImplementations(AmqpClass c)
817784
EmitAutogeneratedSummary(" ", "Private implementation class - do not use directly.");
818785
EmitLine($" internal sealed class {MangleMethodClass(c, m)} : Client.Impl.MethodBase, I{MangleMethodClass(c, m)}");
819786
EmitLine(" {");
820-
EmitLine("");
821787
foreach (AmqpField f in m.m_Fields)
822788
{
823789
EmitLine($" public {MapDomain(f.Domain)} _{MangleMethod(f.Name)};");
@@ -863,69 +829,114 @@ public void EmitClassMethodImplementations(AmqpClass c)
863829
EmitLine("");
864830
EmitLine(" public override int GetRequiredBufferSize()");
865831
EmitLine(" {");
866-
EmitLine(" int bufferSize = 0;");
832+
867833
int bitCount = 0;
834+
int bytesSize = 0;
835+
var commentBuilder = new StringBuilder(" // bytes for ");
868836
foreach (AmqpField f in m.m_Fields)
869837
{
870838
switch (MapDomain(f.Domain))
871839
{
872840
case "byte":
873-
EmitLine($" bufferSize++; // _{MangleMethod(f.Name)} in bytes");
841+
bytesSize++;
842+
commentBuilder.Append('_').Append(MangleMethod(f.Name)).Append(", ");
874843
break;
875844
case "string":
876-
EmitLine($" bufferSize += 1 + Encoding.UTF8.GetByteCount(_{MangleMethod(f.Name)}); // _{MangleMethod(f.Name)} in bytes");
845+
bytesSize++;
846+
commentBuilder.Append("length of _").Append(MangleMethod(f.Name)).Append(", ");
877847
break;
878848
case "byte[]":
879-
EmitLine($" bufferSize += 4 + _{MangleMethod(f.Name)}.Length; // _{MangleMethod(f.Name)} in bytes");
849+
bytesSize += 4;
850+
commentBuilder.Append("length of _").Append(MangleMethod(f.Name)).Append(", ");
880851
break;
881852
case "ushort":
882-
EmitLine($" bufferSize += 2; // _{MangleMethod(f.Name)} in bytes");
853+
bytesSize += 2;
854+
commentBuilder.Append('_').Append(MangleMethod(f.Name)).Append(", ");
883855
break;
884856
case "uint":
885-
EmitLine($" bufferSize += 4; // _{MangleMethod(f.Name)} in bytes");
857+
bytesSize += 4;
858+
commentBuilder.Append('_').Append(MangleMethod(f.Name)).Append(", ");
886859
break;
887860
case "ulong":
888861
case "AmqpTimestamp":
889-
EmitLine($" bufferSize += 8; // _{MangleMethod(f.Name)} in bytes");
862+
bytesSize += 8;
863+
commentBuilder.Append('_').Append(MangleMethod(f.Name)).Append(", ");
890864
break;
891865
case "bool":
866+
if (bitCount == 0)
867+
{
868+
commentBuilder.Append("bit fields, ");
869+
}
892870
bitCount++;
893871
break;
894872
case "IDictionary<string, object>":
895-
EmitLine($" bufferSize += WireFormatting.GetTableByteCount(_{MangleMethod(f.Name)}); // _{MangleMethod(f.Name)} in bytes");
896873
break;
897874
default:
898875
throw new ArgumentOutOfRangeException($"Can't handle size calculations for type = {f.Domain};");
899876
}
900877
}
901878

902-
if (bitCount > 0)
879+
// 13 = " // bytes for "
880+
if (commentBuilder.Length > 14)
881+
{
882+
// cut of last ", "
883+
commentBuilder.Length -= 2;
884+
}
885+
else
903886
{
904-
EmitLine($" bufferSize += {Math.Ceiling(bitCount / 8.0)}; // number of bit fields in bytes");
887+
commentBuilder.Clear();
905888
}
889+
bytesSize += (int)Math.Ceiling(bitCount / 8.0);
890+
EmitLine($" int bufferSize = {bytesSize};{commentBuilder}");
891+
foreach (AmqpField f in m.m_Fields)
892+
{
893+
switch (MapDomain(f.Domain))
894+
{
895+
case "byte":
896+
case "ushort":
897+
case "uint":
898+
case "ulong":
899+
case "AmqpTimestamp":
900+
case "bool":
901+
// size already calculated
902+
break;
903+
case "string":
904+
EmitLine($" bufferSize += Encoding.UTF8.GetByteCount(_{MangleMethod(f.Name)}); // _{MangleMethod(f.Name)} in bytes");
905+
break;
906+
case "byte[]":
907+
EmitLine($" bufferSize += _{MangleMethod(f.Name)}.Length; // _{MangleMethod(f.Name)} in bytes");
908+
break;
909+
case "IDictionary<string, object>":
910+
EmitLine($" bufferSize += WireFormatting.GetTableByteCount(_{MangleMethod(f.Name)}); // _{MangleMethod(f.Name)} in bytes");
911+
break;
912+
default:
913+
throw new ArgumentOutOfRangeException($"Can't handle size calculations for type = {f.Domain};");
914+
}
915+
}
916+
906917
EmitLine(" return bufferSize;");
907918
EmitLine(" }");
908919
EmitLine("");
909920
EmitLine(" public override void AppendArgumentDebugStringTo(StringBuilder sb)");
910921
EmitLine(" {");
911-
EmitLine(" sb.Append(\"(\");");
922+
EmitLine(" sb.Append('(');");
912923
{
913924
int remaining = m.m_Fields.Count;
914925
foreach (AmqpField f in m.m_Fields)
915926
{
916-
Emit($" sb.Append(_{MangleMethod(f.Name)});");
927+
Emit($" sb.Append(_{MangleMethod(f.Name)})");
917928
remaining--;
918929
if (remaining > 0)
919930
{
920-
EmitLine(" sb.Append(\",\");");
931+
EmitLine(".Append(',');");
921932
}
922933
else
923934
{
924-
EmitLine("");
935+
EmitLine(";");
925936
}
926937
}
927938
}
928-
EmitLine(" sb.Append(\")\");");
939+
EmitLine(" sb.Append(')');");
929940
EmitLine(" }");
930941
EmitLine(" }");
931942
}

projects/RabbitMQ.Client/client/api/AmqpTimestamp.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
3939
//---------------------------------------------------------------------------
4040

41+
using System;
42+
4143
namespace RabbitMQ.Client
4244
{
4345
// time representations in mainstream languages: the horror, the horror
@@ -58,7 +60,7 @@ namespace RabbitMQ.Client
5860
/// timestamps are signed or unsigned.
5961
/// </para>
6062
/// </remarks>
61-
public struct AmqpTimestamp
63+
public struct AmqpTimestamp : IEquatable<AmqpTimestamp>
6264
{
6365
/// <summary>
6466
/// Construct an <see cref="AmqpTimestamp"/>.
@@ -74,6 +76,16 @@ public AmqpTimestamp(long unixTime) : this()
7476
/// </summary>
7577
public long UnixTime { get; private set; }
7678

79+
public bool Equals(AmqpTimestamp other) => UnixTime == other.UnixTime;
80+
81+
public override bool Equals(object obj) => obj is AmqpTimestamp other && Equals(other);
82+
83+
public override int GetHashCode() => UnixTime.GetHashCode();
84+
85+
public static bool operator ==(AmqpTimestamp left, AmqpTimestamp right) => left.Equals(right);
86+
87+
public static bool operator !=(AmqpTimestamp left, AmqpTimestamp right) => !left.Equals(right);
88+
7789
/// <summary>
7890
/// Provides a debugger-friendly display.
7991
/// </summary>

0 commit comments

Comments
 (0)