All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Several important changes were made to the conversion code that allowed us to increase the library's performance by about ~4 times.
CPU profiler results before the changes:
CPU profiler results after the changes:
Here's how it was achieved:
-
Conversion logic does not use
NSString
anymore. In the past, when the library was initially developed, we discovered that the nativeString
performance was far from ideal for tasks like parsing. Back then, we thought that the solution would be to switch toNSString
, and it did partly help, although it was never ideal.Since then, a lot of things have changed in Swift.
String
switched to UTF-8 storage and received quite a lot of performance improvements. Note thatNSString
is UTF-16 and keeping using it creates additional overhead because of that.Now it's time to start using
String
again, but it still needs to be done very carefully to avoid spending extra time on reading graphemes instead of reading characters.[!TIP] In order to keep parsing fast, we heavily rely on
UTF8View
. Users need to avoid extra conversion to UTF-8. Please make sure that the filter's content is stored with this encoding. You can ensure this by callingmakeContiguousUTF8
before splitting the filter content into rules to pass them to the converter. If theString
is already contiguous, this call does not cost anything. -
Improved the way
$badfilter
rules are interpreted. The library was using a simple ineffective algorithm without any "indexing". Now$badfilter
rules are grouped by the rule pattern, which significantly speeds up searching for a matching$badfilter
rule. -
Switched to one-pass algorithms in several places:
NetworkRuleParser
,SimpleRegex
,SafariRegex
,CosmeticRuleMarker
, parsing$domain
. -
Replaced
enum
withOptionSet
for handlingNetworkRule
modifiers and content types.
- Added
$from
as an alias of$domain
: #60 (partly, yet to support$to
)
-
Improved the
domain.TLD
implementation. There is still no full support for matchingdomain.TLD
(although, in the future we'll be able to support it better), but it should still be better now. Instead of replacing.TLD
with the seemingly randomly selected top 200 TLDs we now rely on the filters stats and we hope it makes this feature more useful. -
Refactoring
-
Removed
SafariService
;SafariVersion
is now passed down to the underlying code instead of relying on a singleton. -
Removed
allTests
; it's not required anymore in modern Swift. -
Moved the logic from
ConversionResult
toDistributor
. -
Improved unit tests, adding quite a lot of cases that were not covered by tests before.
-
- Improved Safari-compatible regular expression validation. In the past we
relied on a set of simple validation regular expressions that were checking
for known unsupported sequences. Now the check does not rely on any regular
expressions (which made it much faster), but at the same time it is more
thorough and careful. Check out
SafariRegex
to see how it's done.
- Allow specifying the final CB JSON file size limit: #56
$match-case
modifier does not work: #55
- Pseudo-classes
:not()
and:is()
should be handled natively in the same way as:has()
: #47
- Do not split rules with many domains in the
unless-domain
andif-domain
: #51 - Exclude rules containing
if-domain
andunless-domain
with regex values: #53
- Handling provided Safari version for minor version as well, not just the major one.
- Handling provided Safari version.
- Reverted native support of
:has
selector in the content blocker because Safari 16 is not supporting it yet. Corresponding bug.