Skip to content

Commit

Permalink
Use stable hash comparer for nuget/oss model
Browse files Browse the repository at this point in the history
This makes it eaiser to merge PRs when stats are run/updated, since otherwise keys move around since the hashes aren't really stable OOB.
  • Loading branch information
kzu committed Oct 1, 2024
1 parent 7fc4d26 commit ffd6652
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
12 changes: 6 additions & 6 deletions src/Commands/NuGetStatsCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ public override async Task<int> ExecuteAsync(CommandContext context, NuGetStatsS
// The resulting model we'll populate.
OpenSource model;
if (File.Exists(fileName) && settings.Force != true)
model = JsonSerializer.Deserialize<OpenSource>(File.ReadAllText(fileName), JsonOptions.Default) ?? new OpenSource([], [], []);
model = JsonSerializer.Deserialize<OpenSource>(File.ReadAllText(fileName), JsonOptions.Default) ?? new OpenSource();
else
model = new OpenSource([], [], []);
model = new OpenSource();

using var http = httpFactory.CreateClient();

Expand Down Expand Up @@ -399,22 +399,22 @@ await Parallel.ForEachAsync(tasks, paralell, async (source, cancellation) =>

if (contribs != null)
{
model.Repositories.TryAdd(ownerRepo, new(contribs));
model.Repositories.TryAdd(ownerRepo, new(contribs, FnvHashComparer.Default));
}
else
{
// Might not be a GH repo at all, or perhaps it's just empty?
model.Repositories.TryAdd(ownerRepo, []);
model.Repositories.TryAdd(ownerRepo, new(FnvHashComparer.Default));
AnsiConsole.MarkupLine($":warning: [yellow]{link}[/]: no contributors found for [white]{ownerRepo}[/]");
}
}

foreach (var author in model.Repositories[ownerRepo])
model.Authors.GetOrAdd(author, []).Add(ownerRepo);
model.Authors.GetOrAdd(author, _ => new(FnvHashComparer.Default)).Add(ownerRepo);
}

// If we allow non-oss packages, we won't have an ownerRepo, so consider that an empty string.
model.Packages.GetOrAdd(ownerRepo ?? "", []).TryAdd(id.Id, dailyDownloads);
model.Packages.GetOrAdd(ownerRepo ?? "", _ => new(FnvHashComparer.Default)).TryAdd(id.Id, dailyDownloads);
if (ownerRepo != null)
task.Description = $":check_mark_button: [deepskyblue1]{link}[/]: [white]{ownerRepo}[/] [grey]has[/] [lime]{model.Repositories[ownerRepo].Count}[/] [grey]contributors.[/]";
}
Expand Down
39 changes: 39 additions & 0 deletions src/Core/FnvHashComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Runtime.CompilerServices;

namespace Devlooped.Sponsors;

public class FnvHashComparer : IEqualityComparer<string>
{
// FNV-1a 32 bit prime and offset basis
const uint FnvPrime = 0x01000193;
const uint FnvOffsetBasis = 0x811C9DC5;

public static IEqualityComparer<string> Default { get; } = new FnvHashComparer();

public bool Equals(string? x, string? y)
{
// If both are null, or both are same instance, consider them equal
if (x == y) return true;
if (x == null || y == null) return false;
return x.Equals(y, StringComparison.Ordinal); // Use Ordinal for performance
}

public int GetHashCode(string obj)
{
// Convert the 32-bit unsigned hash to a signed int for .NET's GetHashCode
return unchecked((int)Fnv1aHash(obj));
}

// Method to compute FNV-1a hash for a string
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static uint Fnv1aHash(string str)
{
var hash = FnvOffsetBasis;
foreach (var c in str)
{
hash ^= c; // XOR the character
hash *= FnvPrime; // Multiply by the FNV prime
}
return hash;
}
}
4 changes: 4 additions & 0 deletions src/Core/Records.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public record OpenSource(ConcurrentDictionary<string, HashSet<string>> Authors,
OpenSourceSummary? summary;
OpenSourceTotals? totals;

public OpenSource() : this(new(FnvHashComparer.Default), new(FnvHashComparer.Default), new(FnvHashComparer.Default))
{
}

public OpenSourceSummary Summary => summary ??= new(Totals);

public OpenSourceTotals Totals => totals ??= new(this);
Expand Down

0 comments on commit ffd6652

Please sign in to comment.